/* ABOUT — the three panels in about.html: Our Vision, We Value, Our Beliefs.

   Vision and beliefs are visual mockups of the live panels, rebuilt rather than
   screenshotted. We Value is a redesign of one: the live copy word for word, on
   a card of its own instead of on a wash over the photograph — see that section
   below. All three leave out the things the PRD says are wrong with the
   originals:

     DEF-01  the live page runs pagePiling.js, which binds wheel, touchmove and
             keydown and preventDefaults all three. There is no script on this
             page at all, so scrolling is whatever the browser does.
     DEF-03  the live page holds this copy at opacity 0 until wow.js fires. Here
             the CSS default is the finished state and there is nothing to fire.
     DEF-04  the live page sets #1d5aa4 onto sky and #874e20 onto near-white
             sand — 3.64 and 1.65 worst-case, both under AA. On vision and
             beliefs the veils below are what lift them, and the figures beside
             each colour were measured on the rendered page, not estimated: the
             element is hidden, the ground underneath it is captured at that
             exact box, and the worst single pixel in that capture is the number
             written down. Checked at 1920x1000, 1600x900, 1280x800, 1100x760,
             1024x768, 960x900, 834x1112, 740x420, 430x932, 390x844 and 360x640
             — each such figure below is the worst of the eleven.

             We Value now answers it differently. Its copy sits on an opaque
             card, so its two ratios are arithmetic rather than a survey of
             crops — a measured worst case is only ever the worst case someone
             thought to measure, and a card has none left to find.

   The panels share one structure. They differ in which side the words sit on,
   what carries them and which ink they are set in, which is why everything
   common is on .panel and everything else on the modifiers. */

:root {
  /* Vision — the live blue, now on paper rather than over sky. The label wants
     to be denser than the statement it introduces, so it gets the same hue taken
     down; both figures are against #e1eff8, the darkest the paper ever gets. */
  --sky-ink:   #1d5aa4;      /* the statement — 5.87 */
  --sky-label: #17457c;      /* the label — 8.22 */
  --sky-body:  #0c0c0c;      /* 16.68, and what the page reads in */

  /* Values — the live brown, over the empty half of the beach. */
  --sand-ink:  #874e20;
  --sand-body: #2b1a0a;

  /* Beliefs — white type on a dark glass plate, and the four live chip fills
     kept as accents rather than as grounds.

     The live values cannot be used as accents. #584030, #c23a22, #113547 and
     #569200 were chosen to carry white text, so they are all darker than the
     plate they would now sit on — a 2px bar in #113547 on that plate is
     invisible. Each is lightened along its own hue to the most saturated value
     that still clears 4.5 against the lit row it lands on, which is the same
     rule the live reds and greens were darkened by, run the other way. Red
     gives up the most saturation (82% to 35%) because the red primary carries
     so little luminance that no darker tint of it can reach the ratio.

     Both figures per line: on an idle row, then on the selected one, which is
     lifted 7% and is therefore the worse of the two. */
  --acc-1: #fcb88a;      /* from #584030 — 5.75 / 4.68 */
  --acc-2: #ffb3a6;      /* from #c23a22 — 5.71 / 4.65 */
  --acc-3: #84cff5;      /* from #113547 — 5.71 / 4.64 */
  --acc-4: #acd472;      /* from #4a7d00 — 5.77 / 4.69 */

  /* The gold both redesigned panels rule their headings with. */
  --gold: #d8ab5e;

  /* Leaders — each of the four people has one colour on the live site, and it is
     kept, twice, in the two places it can be kept.

     --lead is the live value darkened along its own hue until it clears 4.5 as
     ink. It turns out that is also exactly dark enough to carry white as a
     ground, which is the job it actually does now: the name plate. White on the
     four live values would be 3.69, 2.18, 2.11 and 2.84; on these it is 6.28 to
     6.43. The live values cannot do that job — on
     near-white they carry the four names at 3.22, 1.90, 1.85 and 2.49, so not
     one of the four leaders' names is legible to AA on the page that introduces
     them. The figure beside each is what the darkened value measures on this
     panel's paper. */
  --press:  #eef0f1;     /* the panel's paper */

  --lead-1: #ad2f44;     /* from #f2415f — 5.62 */
  --lead-2: #7a5b20;     /* from #dfa63a — 5.49 */
  --lead-3: #126973;     /* from #22c4d6 — 5.58 */
  --lead-4: #396196;     /* from #5b9bf0 — 5.53 */

  /* Life — the live panel's amber, softened, and a brown deep enough to sit on
     the darkest part of it. Both figures are against #f2d79a, the radial's last
     stop and the only part of the field that can fail. */
  --amber-ink: #6f3f18;   /* 6.23 — #874e20 would be 4.76 here, which is inside
                             the margin the rest of this file works to */



  /* WhatsApp green carries white text at 1.98. This is the same hue taken down
     until white clears AA; the icon disc keeps the bright brand value, so the
     button still reads as WhatsApp at a glance. */
  --wa:     #167c43;     /* white on this — 5.25 */

  --display: "Playfair Display", Georgia, "Times New Roman", serif;
  --body:    "Raleway", system-ui, -apple-system, "Segoe UI", sans-serif;
  --pad:     clamp(22px, 6vw, 120px);
  /* The live panels sit their copy in a Bootstrap offset-2 column, i.e. two
     twelfths in from the edge it is aligned to. That indent is a large part of
     why they read as composed rather than as captions, so it is matched — but
     only while the layout is wide enough to afford it. */
  --inset:   clamp(22px, 16vw, 320px);
}

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

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

body {
  font-family: var(--body);
  color: var(--sky-body);
  line-height: 1.6;
  background: #dceaf7;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; }

:where(a):focus-visible { outline: 3px solid var(--sky-ink); outline-offset: 4px; }

/* ===== THE PANEL — what both share ===== */

.panel {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: start;            /* the live panels set their copy near the top, not centred */
  padding-block: clamp(84px, 15vh, 190px) clamp(56px, 10vh, 120px);
  padding-inline: var(--inset);
  isolation: isolate;
  overflow: hidden;
}

.panel__frame {
  position: absolute; inset: 0; z-index: -2;
  overflow: hidden;
}
/* Absolutely placed inside the frame in both layouts. Left in flow it reports
   its intrinsic height, and on the stacked layout that is what sized the row
   instead of the row sizing it. */
.panel__art {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}


/* Sized off vmin, the way the live theme does it (61–80vmin). A max-width in px
   sprawls on a 1280 laptop until the copy runs out past the end of the veil and
   onto the picture — measured 1.27 there before this changed. */
.panel__copy { max-width: min(64vmin, 640px); }

.panel__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(42px, 7vmin, 104px);
  line-height: 1.02;
  letter-spacing: -.01em;
}

/* ===== 1 · OUR VISION =====
   One sky in two materials. The paper's gradient ends on the colour the
   photograph begins on and the top of the photograph is masked over 46px, so
   the join is not a join — it is the point at which the sky stops being
   something you can set type on.

   Which is the reason for it. The live panel needs a .44 wash over two thirds
   of the frame to get these two lines to 4.94, and that figure is the worst
   pixel of eleven crops rather than a property of the design. Paper has no
   worst pixel: the darkest this type can ever sit on is #e1eff8, the gradient's
   own last stop, and the two ratios below follow from that and nothing else. */

.panel--vision {
  /* Paper above, picture below — at every width. This panel has no second
     layout, which is why none of the responsive block reaches it. */
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  align-content: stretch;
  align-items: stretch;
  justify-items: stretch;
  padding: 0;
  /* What the picture is composited over while it decodes, and the colour the
     paper hands off to. */
  background: #e1eff8;
}

.panel--vision .panel__copy {
  grid-row: 1;
  width: auto;
  max-width: none;
  padding: clamp(54px, 9vh, 126px) clamp(30px, 5vw, 110px) clamp(38px, 6.5vh, 92px);
  /* Three stops, and only the last one matters: it is sampled from the top edge
     of Paravai-1.jpg. Change the photograph and this stop has to be re-sampled
     or the join reappears as a hairline across the panel. */
  background: linear-gradient(180deg, #f7fbfe 0%, #eef6fc 46%, #e1eff8 100%);
}

.panel--vision .panel__frame {
  position: relative;
  inset: auto;
  z-index: 0;
  grid-row: 2;
  min-height: 0;               /* so the row is the remainder, nothing more */
  /* Belt and braces on the join: 46px of cross-fade absorbs whatever the
     sampled colour does not. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 46px);
          mask-image: linear-gradient(180deg, transparent 0, #000 46px);
}
.panel--vision .panel__art { object-position: 50% 50%; }

/* ----- the flock -----
   The four storks are cut out of the photograph and flown separately.

   Paravai-1.jpg is one flat JPEG, so "all four birds move" is not a thing CSS
   can be pointed at — the birds had to be separated first. They were, off the
   file itself rather than by hand: the sky is blue and the storks are not, and
   B minus R says so without argument. Sky and cloud run +25 to +155 across the
   whole frame; every stork pixel, white body, black wing and bluish bundle
   alike, is between -16 and +8. A ramp across that gap is the matte, and the
   ramp is what gives the edges their anti-aliasing back.

   Two passes, because one is not enough. The global separation finds the four
   birds but leaves the bundles hollow — a white cloth lit by a blue sky is
   bluish, so its shading reads as sky. So each bird is then re-cut inside its
   own convex hull on a threshold read off the sky immediately around it: .42 to
   .60 of that local median. For the big stork that is 34 to 49, against a bundle
   interior of 1 to 29 and a sky of 51 to 108 — a gap wide enough that nothing
   in between has to be guessed.

   The sky underneath them is the same file with the birds interpolated away,
   by push-pull over an image pyramid rather than by cv2.inpaint: Telea fills a
   700px hole from its rim inward and left a grey smear where the largest bundle
   had been, which is exactly the part of the sky a moving bird uncovers. The
   pyramid has no interior to lose. At rest the five files recomposite to the
   photograph pixel for pixel, so the panel starts as the picture it always was
   and the fill is only ever seen through the couple of per cent the birds move.

   150KB in five files against 110KB in one. The 40KB buys the parallax.

   No JavaScript, so no scroll-linking: this is the one thing on the page that
   moves on its own clock. It is four composited transforms and nothing else —
   no layout, no paint — and the browser suspends the whole thing when the tab
   is not visible. */

/* container-type is what makes the maths below possible: cqw and cqh are the
   frame's own width and height, so the flock can be given exactly the box
   object-fit: cover hands the photograph, and the storks land on the sky they
   were cut from at every viewport rather than at one. */
.panel--vision .panel__frame { container-type: size; }

.flock {
  position: absolute;
  left: 50%; top: 50%;
  /* The contain box, not the cover box, and the sky underneath is still on
     cover. That mismatch is deliberate and it is the point: a cover crop of a
     2.5:1 frame throws away a third of a 16:9 photograph, and what it throws
     away is birds — the low left stork lost its bundle at 1920x1000 and most of
     itself on a phone. On contain all four are inside the frame at every
     aspect, whole.

     Only the birds need that. The sky is a smooth gradient with nothing in it
     that refers to them, so it can go on covering the frame with no bands at
     the edges, and nothing on screen can tell that the two layers are cropped
     by different rules. It is also why the patches where the birds were
     interpolated out never show: they are smooth sky inside smooth sky, at
     whatever scale.

     92 rather than 100 because contain only guarantees the resting position,
     and these birds do not rest. The low left stork dips 2.5% of the box below
     its own bottom edge at the low point of the bob and another 1.5% under a
     pointer at the bottom of the window; at 100 the frame would clip its bundle
     for a second and a half in every cycle, on exactly the viewport shape where
     the contain box and the frame are the same height. 8% is four per cent of
     margin all round, which is more than anything on this panel travels, and it
     costs a size difference nobody can see without the two side by side. */
  width:  min(92cqw, calc(92cqh * 1921 / 1081));
  height: min(92cqh, calc(92cqw * 1081 / 1921));
  transform: translate(-50%, -50%);
  /* Depth in the frame's own units, so a stork coming forward comes forward by
     the same fraction of the picture on a phone as on a 1920 panel. */
  perspective: 80cqw;
  transform-style: preserve-3d;
  pointer-events: none;

  /* Declared here and nowhere else. flock.js writes these two as an inline
     style on this element, and inline beats a stylesheet rule, so the script
     overrides the default and the storks inherit whichever is current. Declared
     on .stork instead they would shadow the inheritance and the script would
     write to an element nothing was reading — which is exactly what the first
     version of this did. */
  --mx: 0;
  --my: 0;
}

/* The resting transform is written out in full — every function, including the
   ones set to nothing. It is not decoration: a transform list interpolates
   componentwise only against a list with the same functions in the same order,
   and where it cannot, the browser falls back to interpolating matrices, which
   is both slower and wrong through a rotation. The keyframes below repeat the
   same seven functions for the same reason. This is also the state the picture
   is in when nothing is animating, and it is the photograph exactly. */
.stork {
  position: absolute;
  height: auto;
  transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1) rotateX(0deg) rotateY(0deg) rotateZ(0deg) skew(0deg, 0deg);
  transform-style: preserve-3d;
  will-change: transform, translate;
  animation: glide var(--dur) ease-in-out var(--phase) infinite;

  /* Where the pointer has the flock standing. --mx and --my are written by
     flock.js, -1 to 1 across the window, and they default to 0 right here —
     which is what makes the script optional rather than load-bearing: with no
     JS these two lines resolve to no movement and the birds simply fly.

     translate and rotate are separate properties from transform and compose in
     front of it, so the pointer and the glide animation can both drive the same
     stork without either one having to leave room for the other. Percentages
     are of each bird's own box, so the lean stays proportional at every size.

     The transition is long on purpose: a pointer moves in jumps and the flock
     should read as being carried, not as tracking. Nothing here is a spring or
     a loop — one property write per frame, and the easing is the browser's. */
  translate: calc(var(--mx) * var(--px)) calc(var(--my) * var(--py));
  rotate: calc(var(--mx) * var(--pr));
  transition: translate .9s cubic-bezier(.22,.61,.36,1), rotate 1.1s cubic-bezier(.22,.61,.36,1);
}

/* One path, four sizes of it. The amplitudes are per bird and the phases are
   negative, which starts each stork part-way through its own cycle — four birds
   on one keyframe set never line up, and nothing has to be written four times
   to keep them apart.

   The path is mostly vertical and it is deliberately lopsided: up hard to .9 of
   the amplitude, hold near the top, then down past the start to -.75 and back.
   A symmetric bob reads as a float; an uneven one reads as a bird holding
   height and losing it, which is what a stork on a thermal actually does.
   Vertical travel is two to three times the horizontal, because the horizontal
   is a photograph of a bird already in forward flight and only the height is
   free to change.

   3.6 to 4.8 seconds a cycle, which is fast for a stork and is meant to be.
   Note what it costs, because it is the one number here with a real trade-off:
   these are photographs, so the wings do not beat, and past about this rate a
   still silhouette moving quickly starts to read as a jitter rather than as
   flight. It is also where four birds on one keyframe set begin to fall into
   visible step — which is why the four durations are 3.6, 3.9, 4.2 and 4.8 and
   not one of them is a multiple of another. The path and the amplitudes did not
   change with the rate; only the clock did. */
@keyframes glide {
  0%, 100% {
    transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1)
               rotateX(0deg) rotateY(0deg) rotateZ(0deg) skew(0deg, 0deg);
  }
  28% {
    transform: translate3d(calc(var(--dx) * .55), calc(var(--dy) * .9), calc(var(--dz) * .45))
               scale3d(var(--sc), var(--sc), 1)
               rotateX(calc(var(--rx) * .5)) rotateY(calc(var(--ry) * .35)) rotateZ(calc(var(--rz) * .8))
               skew(0deg, 0deg);
  }
  55% {
    transform: translate3d(var(--dx), calc(var(--dy) * .15), var(--dz))
               scale3d(var(--sc), var(--sc), 1)
               rotateX(var(--rx)) rotateY(var(--ry)) rotateZ(calc(var(--rz) * -.35))
               skew(0deg, 0deg);
  }
  78% {
    transform: translate3d(calc(var(--dx) * .45), calc(var(--dy) * -.75), calc(var(--dz) * .3))
               scale3d(1, 1, 1)
               rotateX(calc(var(--rx) * -.4)) rotateY(calc(var(--ry) * .6)) rotateZ(calc(var(--rz) * .5))
               skew(0deg, 0deg);
  }
}

/* Position and size are the bounding box each file was cut from, as a percentage
   of the 1921x1081 photograph — which is the whole of why the flock box has to
   be the cover box and not the frame. The translations are percentages of each
   bird's own width, so the drift stays proportional at every size, and the near
   birds move furthest: that is the parallax, and it is the only thing telling a
   reader these four are at four distances. */
.stork--1 {                                    /* far left, low, smallest */
  left: 5.154%; top: 78.076%; width: 13.222%;
  --dx: 8%; --dy: -15%; --dz: .7cqw;
  --rx: 1.5deg; --ry: 6deg; --rz: 2.2deg; --sc: 1.012;
  --dur: 4.2s; --phase: -1.3s;
  --px: 9%; --py: 7%; --pr: 1.1deg;
}
.stork--2 {                                    /* the near bird, front and centre */
  left: 30.088%; top: 28.030%; width: 37.480%;
  --dx: 4%; --dy: -9%; --dz: 1.8cqw;
  --rx: 1deg; --ry: 3.5deg; --rz: 1.4deg; --sc: 1.008;
  --dur: 3.6s; --phase: -0.7s;
  --px: 5.5%; --py: 4.5%; --pr: .7deg;      /* nearest: least of its own width, most of the frame */
}
.stork--3 {                                    /* right, mid distance */
  left: 75.482%; top: 55.412%; width: 21.707%;
  --dx: 6%; --dy: -13%; --dz: 1.2cqw;
  --rx: 1.2deg; --ry: 5deg; --rz: 1.8deg; --sc: 1.01;
  --dur: 3.9s; --phase: -2.4s;
  --px: 7%; --py: 5.5%; --pr: .9deg;
}
.stork--4 {                                    /* top right, furthest away */
  left: 82.197%; top: 19.426%; width: 14.680%;
  --dx: 9%; --dy: -17%; --dz: .6cqw;
  --rx: 1.6deg; --ry: 7deg; --rz: 2.6deg; --sc: 1.014;
  --dur: 4.8s; --phase: -3.1s;
  --px: 4%; --py: 3%; --pr: .5deg;          /* furthest: barely moves, which is what says so */
}

/* The label, and the rule that runs off it to the edge of the panel. Set in the
   body face rather than the display one: it is naming the thing underneath it,
   not saying anything, and a label that competes with its own statement is the
   mistake this panel is correcting. */
.panel--vision .panel__title {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 34px);
  font-family: var(--body);
  font-weight: 700;
  font-size: clamp(11px, 1.3vmin, 16px);
  letter-spacing: .2em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--sky-label);      /* 8.22 on the paper's last stop */
}
.panel--vision .panel__title::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, rgba(29,90,164,.45) 0%, rgba(29,90,164,.06) 100%);
}

/* The statement, and the largest type on the page. The live site sets this at
   half the size of the word "Vision" above it; it is the only thing on this
   panel anybody came to read, so here it is the other way up. The <br> is the
   live break and is kept — the max-width is only there to stop the measure
   running the full width of a 1920 panel if the break ever goes. */
.panel__line {
  margin-top: clamp(20px, 3.6vh, 48px);
  max-width: min(94%, 1240px);
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(29px, 5.9vmin, 80px);
  line-height: 1.1;
  letter-spacing: -.015em;
  color: var(--sky-ink);        /* 5.87 on the paper's last stop */
}

/* ===== 2 · WE VALUE =====
   Three pearls on the join, at the size of the idea.

   The photograph is a shell holding three pearls, one to each side and a larger
   one in the middle, and this panel is those three pearls: each group is a
   drawn pearl with its name inside it, sitting on the line where the picture
   meets the page. The earlier version had the same idea at the size of a
   bullet — three 20px discs strung on a hairline the stylesheet drew down the
   seam. The hairline is gone because it was standing in for a line the layout
   already has: the edge of the photograph is the thread.

   They are drawn rather than cut out of the photograph. A cut-out would have to
   be re-cut the day the client changes the picture, would arrive as three more
   requests, and would be a photograph of a pearl at whatever resolution the
   file happens to hold; a radial gradient is sharp at any size and costs
   nothing. The five stops are sampled from the file all the same — #fffaf1
   through #e8d5bd to #a58a79 are the middle pearl's own highlight, body and
   shadow, read off kadal-07-1.jpg rather than invented.

   Which is what makes the contrast arithmetic rather than a survey. The names
   sit on a gradient, so the honest question is not what the ratio is where the
   text happens to fall but what it is at the darkest stop in the gradient: the
   names are set in #2b1a0a, which measures 16.09 on the lightest stop and 5.19
   on the darkest. There is no pixel on any pearl at any size where that name
   is under AA, and nothing here had to be measured off a screenshot to say so.

   Same twelve words as the live panel, same wording, same order, and still no
   type on a photograph anywhere. */

.panel--values {
  background: #fbf6ec;               /* the page, and the ground under the join */
  display: grid;
  grid-template-columns: 44% 1fr;
  align-items: stretch;
  justify-items: stretch;
  padding: 0;                        /* both halves are full bleed; the page owns its own margin */
}

/* Out of the absolute position .panel gives it and into the grid as a column of
   its own. It keeps z-index above the page so the shadow below falls onto the
   paper rather than under it — and below the pearls, which sit on top of both. */
.panel--values .panel__frame {
  position: relative;
  inset: auto;
  z-index: 1;
  grid-column: 1;
  /* The picture casts onto the page. Without it the two halves read as two flat
     rectangles that happen to touch. */
  box-shadow: 14px 0 44px rgba(92,60,24,.15);
}
/* Anchored on the shell. In a column this tall cover crops sideways and throws
   away more than half the width, so this is the difference between a panel
   about a shell and a panel about an empty beach. */
.panel--values .panel__art { object-position: 32% 50%; }

/* No left padding, and that is load-bearing: with none, x=0 of this box is the
   join, which is what every pearl below is positioned against. The heading and
   the words carry their own indent instead, off the same two numbers, so all
   four line up whatever the pearls resolve to. */
.panel--values .panel__copy {
  grid-column: 2;
  z-index: 2;                        /* the pearls sit over the picture */
  align-self: center;
  width: auto;
  max-width: none;
  padding: clamp(40px, 8vh, 96px) clamp(30px, 5vw, 110px) clamp(40px, 8vh, 96px) 0;
  --pearl: clamp(112px, 19vmin, 262px);
  --stand: clamp(18px, 2.2vw, 46px);  /* the pearl's clearance from the words */
  /* .58 rather than half, because the middle pearl is 1.16 of the others and
     the three columns of words have to start on the same line whichever pearl
     is beside them. */
  --indent: calc(var(--pearl) * .58 + var(--stand));
}

.panel--values .panel__title {
  margin-left: var(--indent);
  color: var(--sand-ink);            /* 6.21 on the page */
}
/* The same gold hairline the beliefs sheet uses. Two panels, one gesture. */
.panel--values .panel__title::after {
  content: "";
  display: block;
  width: clamp(52px, 8vmin, 96px);
  height: 2px;
  margin-top: .3em;
  background: linear-gradient(90deg, var(--gold) 0%, rgba(216,171,94,0) 100%);
}

.values {
  margin-top: clamp(24px, 4vh, 52px);
  color: var(--sand-body);
}
.values__group {
  position: relative;
  /* Column flow, because grid blockifies its children: left as rows, the three
     words each took a line of their own and the dt's separator margins went
     with them. One row of three columns is what the markup means. */
  display: grid;
  grid-auto-flow: column;
  justify-content: start;
  align-content: center;
  min-height: var(--size);
  padding-left: var(--indent);
  --size: var(--pearl);
  --nudge: 0px;
}
/* The photograph's own arrangement: a smaller pearl, a larger one, a smaller
   one again. The nudges are what stop three discs on one axis reading as a
   drawn diagram — pearls in a shell do not queue. */
.values__group:nth-child(2) { --size: calc(var(--pearl) * 1.16); --nudge: -.055em; }
.values__group:nth-child(3) { --size: calc(var(--pearl) * .94);  --nudge:  .07em; }

.values__group + .values__group { margin-top: clamp(20px, 3.4vh, 48px); }

/* The pearl is the term, not a bullet beside it. Centred on x=0 of the copy,
   which is the join, so half of it lies over the photograph and half over the
   page and it belongs to neither. */
.values dt {
  position: absolute;
  left: var(--nudge);
  top: 50%;
  width: var(--size);
  height: var(--size);
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  border-radius: 50%;
  /* Sampled from the middle pearl in kadal-07-1.jpg: highlight, body, the turn
     of the shoulder, and the shadow where it meets the shell. */
  background: radial-gradient(circle at 33% 26%,
    #ffffff 0%,
    #fffdf7 8%,
    #f8ecdb 36%,
    #ead8c0 64%,
    #d3b895 85%,
    #a98d72 100%);
  box-shadow: inset -2px -3px 10px rgba(120,88,50,.28),
              inset  2px  3px  8px rgba(255,255,255,.55),
              0 10px 26px rgba(96,62,25,.24),
              0 2px 5px rgba(96,62,25,.18);
  font-family: var(--display);
  font-weight: 700;
  /* A fraction of the pearl rather than a clamp of its own: the longest of the
     three names is nine characters, which sets at .69 of the diameter at this
     ratio, so it fits inside every pearl at every size and there is no second
     number to keep in step with the first. */
  font-size: calc(var(--size) * .14);
  line-height: 1.1;
  letter-spacing: -.01em;
  text-align: center;
  color: var(--sand-body);           /* 16.09 on the lightest stop, 5.19 on the darkest */
}

/* The three words run along one line instead of down three. Twelve words in a
   column was what made the live panel need a wide layout to itself and a redraw
   on short screens; three lines of three reads in one pass and fits every
   viewport this page has. */
.values dd {
  display: inline;
  margin-left: 0;                /* the UA indent would imply a hierarchy that is not there */
  font-weight: 400;
  font-size: clamp(16px, 2.4vmin, 30px);
  line-height: 1.55;
}
.values dd + dd::before {
  content: "\00B7";
  margin: 0 .55em;
  color: rgba(135,78,32,.75);
}

/* ===== 3 · OUR BELIEFS =====
   A contact sheet, not a backdrop with a list on it.

   The panel this replaces — and the live panel it replaces in turn — both put
   one photograph on screen and held the other three behind an interaction. Four
   frames side by side ends that: every picture the client supplied is visible at
   first paint, every statement is readable next to the one it belongs to, and
   the thing the pointer drives is a grid template rather than which of four
   stacked images is at opacity 1.

   The frame opens under the pointer. The radio group is still here and still
   does the same job — it is what a tap and the arrow keys move, and what holds
   an open frame open once the pointer leaves — but on a machine with a mouse
   the strip answers the mouse, and nothing has to be clicked to be read.

   There is no ring any more. A frame that is open is marked by being open: full
   colour where the other three are held back, its number in its own accent, and
   a 2px rule of that accent along the top of its caption band. Those three were
   always doing the work; the ring was a fourth mark on top of them, and a
   3px stroke drawn round a frame that is already twice the width of its
   neighbours is saying a thing the layout has said.

   Contrast is exact again, and for the third time by the same method: the type
   never touches a photograph. It sits in a caption band at .92, whose lightest
   possible ground is 8% of a white pixel — rgb(29,32,34) — giving 13.71 for an
   idle caption and 16.34 for the selected one. The heading is on the sheet
   itself at 17.87. None of the three can move with a crop. */

.panel--beliefs {
  background: linear-gradient(180deg, #14181a 0%, #0d1113 100%);
  /* The strip wants the width. The two-twelfths inset the other panels use for
     their copy would cost it 640px at 1920. */
  padding-inline: clamp(22px, 6vw, 120px);
  align-content: center;
  align-items: center;
  justify-items: stretch;
}

/* The radio inputs drive the whole panel and are never seen. Kept in the layout
   rather than display:none, because a display:none input is not focusable and
   the arrow-key behaviour that makes this usable by keyboard would go with it. */
.belief {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}

.panel--beliefs .panel__copy { width: auto; max-width: none; }
.panel--beliefs .panel__title { color: #fff; }        /* 17.87 on the sheet */
/* The same gold hairline the values card uses. Two panels, one gesture — it is
   what says they were redesigned together rather than one at a time. */
.panel--beliefs .panel__title::after {
  content: "";
  display: block;
  width: clamp(52px, 8vmin, 96px);
  height: 2px;
  margin-top: .3em;
  background: linear-gradient(90deg, var(--gold) 0%, rgba(216,171,94,0) 100%);
}

/* The strip. A definite height rather than an aspect ratio: four frames whose
   width is about to change by a factor of two need a height that does not move
   with it, or every selection would resize the panel under the reader.

   grid-template-columns is what the pointer and the selection both animate.
   Browsers that will not interpolate it snap to the new template instead, which
   is the whole behaviour — nothing here waits on a transition, and the panel is
   complete at whichever end of it you land. */
.sheet {
  /* The three durations the panel moves at, in one place, because they are one
     movement seen from three sides — the frame widening, its photograph coming
     back and its accent arriving — and they only read as one if they are timed
     together. They are deliberately slow. Under a pointer this opens on a
     mouse crossing a boundary rather than on a decision, and at the .55s the
     click version used the strip snapped sideways every time the pointer passed
     over it, which reads as a flinch. Near a second it reads as the strip
     making room. The marks come in first and the frame settles last, so the
     movement resolves rather than stopping. */
  --open: .95s;                      /* the strip redistributing */
  --lift: .78s;                      /* the photograph coming back to colour */
  --mark: .5s;                       /* the number and the caption's rule */
  --ease: cubic-bezier(.22,.61,.36,1);

  list-style: none;
  padding: 0;
  margin-top: clamp(18px, 3vmin, 36px);
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  gap: clamp(5px, .8vmin, 12px);
  height: clamp(300px, 54vh, 600px);
  transition: grid-template-columns var(--open) var(--ease);
}

:where(#b1:checked ~ .panel__copy) .sheet { grid-template-columns: 2.2fr 1fr 1fr 1fr; }
:where(#b2:checked ~ .panel__copy) .sheet { grid-template-columns: 1fr 2.2fr 1fr 1fr; }
:where(#b3:checked ~ .panel__copy) .sheet { grid-template-columns: 1fr 1fr 2.2fr 1fr; }
:where(#b4:checked ~ .panel__copy) .sheet { grid-template-columns: 1fr 1fr 1fr 2.2fr; }

/* Every accent is keyed off the same for="bN" the rest of this panel is keyed
   off, so there is one place to be wrong rather than two — an nth-child list
   here would silently drift the moment a belief was reordered. */
.sheet label[for="b1"] { --accent: var(--acc-1); }
.sheet label[for="b2"] { --accent: var(--acc-2); }
.sheet label[for="b3"] { --accent: var(--acc-3); }
.sheet label[for="b4"] { --accent: var(--acc-4); }

.sheet__frame { counter-increment: belief; min-width: 0; }
.sheet { counter-reset: belief; }

.sheet label {
  position: relative;
  display: block;
  height: 100%;
  overflow: hidden;
  border-radius: 3px;
  background: #0f1416;              /* what a frame is before its photograph decodes */
  cursor: pointer;
}
.sheet img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* Idle frames are held back rather than hidden: this is a contact sheet, and
     on one of those the frames you have not chosen are still there to read. */
  filter: saturate(.42) brightness(.58);
  transition: filter var(--lift) var(--ease);
}

/* Every one of the four was shot as a background for right-hand copy, so every
   subject sits left of centre — the kangaroo at 24%, the nest at 27%, the
   squirrel at 30%, the kingfisher at 45%. In a frame this narrow cover crops
   sideways and half the width is thrown away, so each is anchored on its own
   subject instead of on a single average that would lose two of them. */
.sheet label[for="b1"] img { object-position: 24% 46%; }
.sheet label[for="b2"] img { object-position: 30% 58%; }
.sheet label[for="b3"] img { object-position: 45% 50%; }
.sheet label[for="b4"] img { object-position: 27% 50%; }

/* The frame number, in the corner, on its own solid chip — the one way to put
   a numeral over a photograph and still know what it measures. Generated rather
   than written into the markup because it is ordinal decoration, not copy: the
   four beliefs are not ranked and the live panel does not number them. */
.sheet label::before {
  content: counter(belief, decimal-leading-zero);
  position: absolute;
  top: 0; left: 0;
  z-index: 2;
  padding: .34em .62em .38em;
  background: rgba(9,13,15,.92);
  border-bottom-right-radius: 3px;
  font-family: var(--display);
  font-size: clamp(12px, 1.5vmin, 18px);
  letter-spacing: .04em;
  color: rgba(255,255,255,.70);      /* 8.61 on the band */
  transition: color var(--mark) var(--ease);
}

/* The caption, burned into the bottom of the frame. A band rather than a
   gradient: a gradient's ratio depends on what is underneath it, and underneath
   this one there are four photographs and no fixed crop. */
.sheet__cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 1;
  padding: clamp(9px, 1.3vmin, 16px) clamp(10px, 1.4vmin, 18px);
  background: rgba(9,13,15,.92);
  color: #e8ecea;                    /* 13.71 on the band */
  font-weight: 500;
  font-size: clamp(13px, 1.55vmin, 20px);
  line-height: 1.32;
  letter-spacing: .002em;
  transition: color var(--mark) var(--ease), box-shadow var(--mark) var(--ease);
}

/* The selected frame. */
:where(#b1:checked ~ .panel__copy) .sheet label[for="b1"] img,
:where(#b2:checked ~ .panel__copy) .sheet label[for="b2"] img,
:where(#b3:checked ~ .panel__copy) .sheet label[for="b3"] img,
:where(#b4:checked ~ .panel__copy) .sheet label[for="b4"] img { filter: none; }

:where(#b1:checked ~ .panel__copy) .sheet label[for="b1"]::before,
:where(#b2:checked ~ .panel__copy) .sheet label[for="b2"]::before,
:where(#b3:checked ~ .panel__copy) .sheet label[for="b3"]::before,
:where(#b4:checked ~ .panel__copy) .sheet label[for="b4"]::before { color: var(--accent); }

:where(#b1:checked ~ .panel__copy) .sheet label[for="b1"] .sheet__cap,
:where(#b2:checked ~ .panel__copy) .sheet label[for="b2"] .sheet__cap,
:where(#b3:checked ~ .panel__copy) .sheet label[for="b3"] .sheet__cap,
:where(#b4:checked ~ .panel__copy) .sheet label[for="b4"] .sheet__cap {
  color: #fff;                       /* 16.34 on the band */
  /* A rule in the frame's own accent along the top of the band, drawn as a
     shadow so it costs no layout and cannot shift the caption by a pixel. */
  box-shadow: inset 0 2px 0 0 var(--accent);
}

/* ----- the pointer opens the frame -----
   The strip answers the pointer on anything that has one, and the radio group
   is what is left when there is not: a tap still selects, the arrow keys still
   move, and a browser without :has() gets exactly the behaviour this panel had
   before — which is why the selection was never replaced with hover, only put
   underneath it.

   While the pointer is anywhere in the strip the selected frame stands down, so
   there is one open frame and not two. The pointer wins because it is the more
   recent statement of intent; leave the strip and the selection comes back.

   All of this is a specificity arrangement rather than a stack of overrides:
   the :checked rules above are wrapped in :where(), which zeroes the id they
   would otherwise carry, and an id beats any number of classes. Without that
   wrapper nothing below could reach them. */
@media (hover: hover) and (pointer: fine) {
  .sheet:has(label:hover) label[for] img       { filter: saturate(.42) brightness(.58); }
  .sheet:has(label:hover) label[for]::before   { color: rgba(255,255,255,.70); }
  .sheet:has(label:hover) label[for] .sheet__cap { color: #e8ecea; box-shadow: none; }

  .sheet .sheet__frame label[for]:hover img     { filter: none; }
  .sheet .sheet__frame label[for]:hover::before { color: var(--accent); }
  .sheet .sheet__frame label[for]:hover .sheet__cap {
    color: #fff;                     /* 16.34 on the band, the same as selected */
    box-shadow: inset 0 2px 0 0 var(--accent);
  }
}

/* The template follows the pointer, on the same transition the selection uses.
   Held to the width where the strip is still four columns — below 700px it is
   four rows and the rows are driven further down, on that threshold. */
@media (hover: hover) and (pointer: fine) and (min-width: 700px) {
  .sheet:has(.sheet__frame:nth-child(1) label:hover) { grid-template-columns: 2.2fr 1fr 1fr 1fr; }
  .sheet:has(.sheet__frame:nth-child(2) label:hover) { grid-template-columns: 1fr 2.2fr 1fr 1fr; }
  .sheet:has(.sheet__frame:nth-child(3) label:hover) { grid-template-columns: 1fr 1fr 2.2fr 1fr; }
  .sheet:has(.sheet__frame:nth-child(4) label:hover) { grid-template-columns: 1fr 1fr 1fr 2.2fr; }
}

/* The input is off-screen, so the focus ring has to be put back on the frame it
   controls or the radio group is unusable by keyboard. */
#b1:focus-visible ~ .panel__copy .sheet label[for="b1"],
#b2:focus-visible ~ .panel__copy .sheet label[for="b2"],
#b3:focus-visible ~ .panel__copy .sheet label[for="b3"],
#b4:focus-visible ~ .panel__copy .sheet label[for="b4"] {
  outline: 3px solid #fff; outline-offset: 3px;
}

/* ===== 4 · LEADERS OF EASTON =====
   A lit rail on black. Four portraits standing at four different heights, the
   one under the pointer at full brightness with its name in white and its role
   in that person's own colour, the other three held back — the same idea the
   contact sheet two panels up is built on, and the same controls.

   The ground is what changed, and it pays for itself immediately. On near-white
   the four live colours are unusable: #f2415f, #dfa63a, #22c4d6 and #5b9bf0 set
   the four names at 3.22, 1.90, 1.85 and 2.49, which is what the live site
   publishes, and it is why the earlier version of this panel had to darken all
   four until they could be a ground instead. On #0b0d0e the same four values,
   untouched, measure 5.28, 8.95, 9.21 and 6.86. The palette did not need
   correcting. It needed a panel it could sit on.

   Every ratio here is arithmetic rather than a survey, because no type on this
   panel touches a photograph: the names sit under the cards on the flat ground,
   the way they do on the reference this is built from.

   The portraits are 198x201 and that is all the resolution there is, which sets
   the size of everything else. At 5:6 a 250px card is a 1.49x enlargement, and
   the columns are capped there rather than filling their track — a rail that
   spread four of these across a 1920 panel would be a 2x blow-up of a soft
   black-and-white scan.

   The stagger is keyed by position and the colour by initials, which is the rule
   the rest of this file works to: a rhythm is about where a card sits, and a
   colour is about the person. */

.panel--leaders {
  background: #0b0d0e;
  align-content: center;
  justify-items: stretch;
  padding-block: clamp(54px, 9vh, 126px);
  padding-inline: clamp(30px, 5vw, 110px);
}
.panel--leaders .panel__copy { width: auto; max-width: none; }

/* The radios drive the panel and are never seen. Kept in the layout rather than
   display:none for the reason the beliefs strip states: a display:none input is
   not focusable, and the arrow-key behaviour that makes this usable without a
   mouse would go with it. */
.leader-pick {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}

.panel--leaders .panel__title {
  font-size: clamp(32px, 5vmin, 68px);
  color: #fff;                       /* 19.48 */
  margin-bottom: clamp(26px, 4.6vh, 62px);
}

/* The rail takes the width it can use at its own resolution; the paragraph
   takes the rest. An even split would either stretch four small photographs
   across a 1920 panel or leave a third of it empty beside them. */
.leaders__body {
  display: grid;
  /* max-content rather than 1fr on the rail: 1fr hands it the whole track and
     the cards, capped at their own resolution, leave the slack in the middle —
     340px of black between the last card and the paragraph at 1920. Sized to
     its content, the two sit together and the slack falls at the panel edge
     where it reads as margin. */
  grid-template-columns: minmax(0, max-content) clamp(230px, 20vw, 360px);
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
  justify-content: start;
}
.leaders__intro {
  font-size: clamp(15px, 1.75vmin, 21px);
  line-height: 1.65;
  color: rgba(255,255,255,.72);      /* 10.15 */
}

.leaders {
  list-style: none;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 250px));
  gap: clamp(12px, 1.8vw, 34px);
  align-items: start;
}

/* Keyed by initials, not by position — nth-child would hand the wrong colour to
   the wrong person the day someone is added or the order changes. The wash is
   the same value at the alpha the watermark can afford, written out rather than
   mixed at runtime, which is the rule the rest of the page follows.

   Those four alphas are not a taste. The watermark runs behind the name and the
   role, so it is a ground, and everything that crosses it has to still pass on
   it: at .20 the held-back role measured 3.76 to 4.37 and the lit role in its
   own colour 4.33, all under AA, on the one panel whose whole argument is that
   this palette is legible. Each alpha here is the highest value at which the
   weakest ink on that colour still clears 4.6 — role 4.60 to 4.65, name 6.26 to
   6.33, the colour itself on its own wash 4.60 to 8.04. Red is the outlier at
   .15 because the red primary carries so little luminance that a wash of it
   barely lifts the ground; cyan and gold have to stop at .10. */
.leader--pp { --ink: #f2415f; --wash: rgba(242,65,95,.15);  --ink-print: var(--lead-1); }   /* 5.28 on the ground, 5.62 on paper */
.leader--sa { --ink: #dfa63a; --wash: rgba(223,166,58,.10); --ink-print: var(--lead-2); }   /* 8.95 / 5.49 */
.leader--ks { --ink: #22c4d6; --wash: rgba(34,196,214,.10); --ink-print: var(--lead-3); }   /* 9.21 / 5.58 */
.leader--sr { --ink: #5b9bf0; --wash: rgba(91,155,240,.12); --ink-print: var(--lead-4); }   /* 6.86 / 5.53 */

/* The rhythm the reference is built on: four cards that do not share a
   baseline. Keyed by position, because that is what a rhythm is. */
.leader:nth-child(2) { margin-top: clamp(14px, 4.2vmin, 54px); }
.leader:nth-child(3) { margin-top: clamp(5px,  1.4vmin, 18px); }
.leader:nth-child(4) { margin-top: clamp(18px, 5.6vmin, 72px); }

.leader label {
  display: block;
  cursor: pointer;
  transition: transform .55s cubic-bezier(.22,.61,.36,1);
}

.leader__shot {
  position: relative;
  display: block;
  aspect-ratio: 5 / 6;
  overflow: hidden;
  border-radius: 4px;
  background: #15181a;               /* what a card is before its portrait decodes */
}
/* Absolutely placed rather than sized at 100%: a percentage height against a
   parent whose own height comes from an aspect ratio does not resolve in every
   engine, and where it does not the image falls back to its intrinsic ratio,
   object-fit stops applying and overflow crops the top. That is exactly what
   happened here at v=22 — four plates of flat colour with no faces in them. */
.leader__shot img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 34%;          /* the eyeline, not the middle of the crop */
  /* Held back rather than hidden, and the dimming does two jobs at once: it
     says which card is not the chosen one, and it stops three white rectangles
     glaring out of a black panel. These were shot on white. */
  filter: brightness(.24) contrast(1.06);
  transition: filter .55s ease;
}

.leader__body {
  position: relative;
  display: block;
  overflow: hidden;                  /* the watermark runs past the corner */
  padding: clamp(11px, 1.5vmin, 18px) 0 0;
}
/* The live panel's giant faded initials, which had nowhere to go once the
   coloured field they were printed on did. Behind the name, in that person's
   own colour, running off the corner — which is what a watermark is for. */
.leader__mark {
  position: absolute;
  right: 0;
  bottom: -.3em;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(26px, 5.4vmin, 78px);
  line-height: 1;
  letter-spacing: .01em;
  color: var(--wash);
  pointer-events: none;
}

/* Both sit over the mark, which is why they are positioned at all. */
.leader__name {
  position: relative;
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(16px, 1.95vmin, 27px);
  line-height: 1.16;
  letter-spacing: -.006em;
  color: rgba(255,255,255,.60);      /* 7.26 — held back, never below AA */
  transition: color .45s ease;
}
/* Set like a credit rather than like a caption. */
.leader__role {
  position: relative;
  display: block;
  margin-top: .6em;
  font-weight: 600;
  font-size: clamp(10px, 1.05vmin, 13px);
  letter-spacing: .13em;
  text-transform: uppercase;
  line-height: 1.42;
  color: rgba(255,255,255,.50);      /* 5.33 */
  transition: color .45s ease;
}

/* ----- the chosen card ----- */
:where(#l1:checked ~ .panel__copy) .leaders label[for="l1"],
:where(#l2:checked ~ .panel__copy) .leaders label[for="l2"],
:where(#l3:checked ~ .panel__copy) .leaders label[for="l3"],
:where(#l4:checked ~ .panel__copy) .leaders label[for="l4"] {
  transform: translateY(clamp(-22px, -1.8vmin, -8px));
}
:where(#l1:checked ~ .panel__copy) .leaders label[for="l1"] img,
:where(#l2:checked ~ .panel__copy) .leaders label[for="l2"] img,
:where(#l3:checked ~ .panel__copy) .leaders label[for="l3"] img,
:where(#l4:checked ~ .panel__copy) .leaders label[for="l4"] img { filter: none; }

:where(#l1:checked ~ .panel__copy) .leaders label[for="l1"] .leader__name,
:where(#l2:checked ~ .panel__copy) .leaders label[for="l2"] .leader__name,
:where(#l3:checked ~ .panel__copy) .leaders label[for="l3"] .leader__name,
:where(#l4:checked ~ .panel__copy) .leaders label[for="l4"] .leader__name { color: #fff; }

:where(#l1:checked ~ .panel__copy) .leaders label[for="l1"] .leader__role,
:where(#l2:checked ~ .panel__copy) .leaders label[for="l2"] .leader__role,
:where(#l3:checked ~ .panel__copy) .leaders label[for="l3"] .leader__role,
:where(#l4:checked ~ .panel__copy) .leaders label[for="l4"] .leader__role { color: var(--ink); }

/* ----- and the pointer, in front of the selection -----
   The same arrangement the contact sheet uses and for the same reason: the
   :checked rules above are wrapped in :where(), which zeroes the id they would
   otherwise carry, so a hover rule can reach them at all. While the pointer is
   anywhere in the rail the chosen card stands down, so there is one lit card
   and never two. */
@media (hover: hover) and (pointer: fine) {
  .leaders:has(label:hover) label[for]                { transform: none; }
  .leaders:has(label:hover) label[for] img            { filter: brightness(.24) contrast(1.06); }
  .leaders:has(label:hover) label[for] .leader__name  { color: rgba(255,255,255,.60); }
  .leaders:has(label:hover) label[for] .leader__role  { color: rgba(255,255,255,.50); }

  .leaders .leader label[for]:hover                   { transform: translateY(clamp(-22px, -1.8vmin, -8px)); }
  .leaders .leader label[for]:hover img               { filter: none; }
  .leaders .leader label[for]:hover .leader__name     { color: #fff; }
  .leaders .leader label[for]:hover .leader__role     { color: var(--ink); }
}

/* The input is off-screen, so the focus ring has to be put back on the card it
   controls or the group is unusable by keyboard. */
#l1:focus-visible ~ .panel__copy .leaders label[for="l1"] .leader__shot,
#l2:focus-visible ~ .panel__copy .leaders label[for="l2"] .leader__shot,
#l3:focus-visible ~ .panel__copy .leaders label[for="l3"] .leader__shot,
#l4:focus-visible ~ .panel__copy .leaders label[for="l4"] .leader__shot {
  outline: 3px solid #fff; outline-offset: 3px;
}

/* ===== 5 · LIFE @ EASTON =====
   A dial. The collage is the rim, the ten years are engraved inside it, and the
   words stand in the opening.

   The panel is built on a measurement rather than on a resemblance. The file is
   not a free-form cut-out: both of its edges are circular arcs about one point.
   Fitted to its own alpha channel, that point is (920.0, 237.8) in the 900x990
   source, the inner edge is r=511.3 and the outer r=878.4 — worst-case residual
   0.8px on the inner arc and 5.8px on the outer. The collage is a ring segment,
   which is to say one blade of a lens iris, and this panel takes it for one.

   So there is no object-position here and no crop. --R is that inner radius on
   screen and every length in the layout is a multiple of it, the photograph
   included: it is placed by its own geometry at whatever size --R resolves to,
   scaled and moved but never cut. --pivot-y is fixed at .465R, which is the one
   offset that lands the picture's top edge on the panel's at every viewport.

   That is what the decade was missing. It used to be a ruler down the far right
   edge — a scale beside a picture it had no relationship with, and the first
   thing to look orphaned when the panel got short, which is what a 1280x583
   window showed. Here it is struck at .72R about the same centre, so it follows
   the rim because it is concentric with it by construction rather than by eye,
   and the ticks reach out from each year and stop short of the photographs.

   The ticks fade going back in time. The years do not: a fade on a hairline
   costs nothing, a fade on type costs contrast, and all ten years stay one ink
   at 5.56 on the field's darkest stop.

   It is still not a radio group. The collage is one image, not ten galleries,
   so a year picker would be a control that changes nothing — it invites a click
   and answers with silence. If the client ever supplies a set per year the
   markup is already a list of years in order, and it becomes Our Beliefs.

   --R is capped at 620px because the client supplied 900x990 and nothing
   larger. Uncapped, .68 of a 1440-tall panel draws this file at 1.6x and the
   faces go soft — at 1600x900 an earlier .776 and a 700px cap already did, and
   it is the one thing in this panel a screenshot shows before the geometry.
   620px is 1.21x, which these photographs survive. Past 1350px of panel height
   the floor below wins anyway and takes the enlargement, because a picture that
   stops halfway down the field is the worse of the two faults. */

.panel--life {
  /* Softened from the live amber, and a radial rather than the live hex lattice:
     a lattice at the opacity that one runs at is a texture nobody sees and every
     compositor pays for. It is also what shows through the collage's alpha. */
  background: radial-gradient(120% 92% at 18% 10%, #fbeccb 0%, #f6e0a8 58%, #f2d79a 100%);

  /* Height sets the radius — the picture's top edge lands on the panel's at any
     radius, so .68 of the panel is only about how far past the bottom one it
     carries — and width caps it, because the opening is
     a disc of this radius and a radius wider than the room left of it leaves no
     rim on screen at all. Uncapped at 1024x768 the void ate all but 65px of the
     photographs. The floor is the other half of the same argument: below .517
     of the panel the picture is shorter than the panel and stops mid-field with
     a hard edge where the bottom row of photographs ends, so on a 1440-tall
     screen the floor wins over the cap and the file takes the enlargement. */
  --R: clamp(51.7svh, min(68svh, 46vw), 620px);
  /* Pinned to the panel until the panel is wider than the picture, then pinned
     to the picture: past that point a proportional pivot walks the collage off
     the left edge and strands it in the middle of the field. */
  --pivot-x: min(58vw, calc(var(--R) * 1.74));
  --pivot-y: calc(var(--R) * .46508);   /* 237.8 / 511.3 */
  --gutter: clamp(30px, 5vw, 110px);

  position: relative;
  display: grid;
  /* Centred on the opening rather than started at the top of it. Hung level
     with 2020 the copy and the scale read as one object, but everything left
     over then pooled into one empty half-panel underneath; centred, the field
     that is left reads as the margin of a disc, which is what it is. */
  align-content: center;
  padding: clamp(40px, 7vh, 90px) var(--gutter);
}

/* The stage the picture is placed on, and the only thing on this panel that
   clips: the collage bleeds off the left edge and past the bottom one. */
.life__art {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}
/* Sized and offset from the pivot, so the arc centre is a known point on the
   panel rather than wherever a crop happened to leave it: 900/511.3 wide, and
   -920.0/511.3 and -237.8/511.3 from that centre to its top left corner. The
   max-width reset is load-bearing — the global img rule would clamp this to the
   stage width and take every ratio in the panel with it. */
.life__art img {
  position: absolute;
  left: var(--pivot-x);
  top:  var(--pivot-y);
  width: calc(var(--R) * 1.76022);
  height: auto;
  max-width: none;
  margin-left: calc(var(--R) * -1.79934);
  margin-top:  calc(var(--R) * -.46508);
}

/* Inside the opening. .34R back from the centre clears the closest year — 2011,
   which comes furthest round the arc — by .21R at every size, and it is written
   against the pivot rather than as a fraction of the panel so that clearance is
   the same clearance at every viewport. The gutter is subtracted because a
   margin starts at the content edge while the pivot is measured from the
   panel's. */
.panel--life .panel__copy {
  position: relative;
  width: auto;
  max-width: none;
  margin-left: calc(var(--pivot-x) - var(--R) * .34 - var(--gutter));
}

/* Both sizes take the larger of a vmin and a vw term rather than vmin alone.
   The opening is as wide as the panel and only as tall as the picture, so on a
   short landscape window a vmin scale is reading off the one dimension that has
   nothing to do with the space the type is standing in — at 1280x583 it landed
   on the 15px floor with 600px of field beside it. */
.panel--life .panel__title {
  font-size: clamp(36px, max(5.4vmin, 3.2vw), 88px);
  color: var(--amber-ink);           /* 6.23 on the field's darkest stop */
}
/* The ring around the @, as the live heading has it. Sized in em so it is one
   number at every viewport rather than a clamp of its own that would have to be
   kept in step with the heading's. */
.panel--life .at {
  display: inline-grid;
  place-items: center;
  width: .96em; height: .96em;
  margin-inline: .05em;
  border: .055em solid rgba(111,63,24,.42);
  border-radius: 50%;
  font-size: .82em;
  line-height: 1;
  vertical-align: -.06em;
}

.panel--life .panel__copy p {
  max-width: 62ch;
  font-size: clamp(16px, max(1.8vmin, 1.05vw), 24px);
  line-height: 1.72;
  color: var(--sand-body);           /* 11.92 */
}
.panel--life .panel__copy p:first-of-type { margin-top: clamp(18px, 3.2vh, 40px); }
.panel--life .panel__copy p + p { margin-top: 1.15em; }

/* ----- the decade, struck on the rim ----- */

/* A zero-sized box at the arc centre. It carries nothing itself; the ten years
   hang off it in polar coordinates, which is why the list is out of flow here
   and back in flow the moment the panel stacks. */
.decade {
  position: absolute;
  left: var(--pivot-x);
  top:  var(--pivot-y);
  width: 0; height: 0;
  margin: 0; padding: 0;
  list-style: none;
  --arc: calc(var(--R) * .72);       /* where the inner edge of each year sits */
}

/* Rotate to the year's angle, run out to the arc, rotate back so the number
   stays upright, then shift the box so the point on the arc is its inner edge
   rather than its centre. The origin has to be the corner: the corner is what
   is sitting on the pivot. */
.decade li {
  position: absolute;
  left: 0; top: 0;
  transform-origin: 0 0;
  transform: rotate(var(--a))
             translateX(calc(var(--arc) * -1))
             rotate(calc(var(--a) * -1))
             translate(-100%, -50%);
  white-space: nowrap;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(15px, 1.9vmin, 25px);
  line-height: 1.25;
  letter-spacing: .01em;
  color: rgba(43,26,10,.72);         /* 5.56 — one ink for all ten */
  --a: calc(25deg - (var(--i) - 1) * 7.2deg);
}
/* 65 degrees of arc, newest at the top. Keyed by position, because position is
   the whole of what a scale means — unlike the leaders' colours, which are
   keyed by person for the opposite reason. */
.decade li:nth-child(1)  { --i: 1 }
.decade li:nth-child(2)  { --i: 2 }
.decade li:nth-child(3)  { --i: 3 }
.decade li:nth-child(4)  { --i: 4 }
.decade li:nth-child(5)  { --i: 5 }
.decade li:nth-child(6)  { --i: 6 }
.decade li:nth-child(7)  { --i: 7 }
.decade li:nth-child(8)  { --i: 8 }
.decade li:nth-child(9)  { --i: 9 }
.decade li:nth-child(10) { --i: 10 }

/* The tick, laid back down the radius the year came out on: the number was
   turned upright, so the tick has to be turned by the same angle again to point
   at the centre. */
.decade li::after {
  content: "";
  position: absolute;
  right: 100%; top: 50%;
  width: calc(var(--R) * .10);
  height: 1px;
  margin-right: calc(var(--R) * .022);
  transform-origin: 100% 50%;
  transform: translateY(-50%) rotate(var(--a));
  background: rgba(111,63,24,.62);
  opacity: calc(1 - (var(--i) - 1) * .075);
}
/* Longer every fifth year — 2020 and 2015 — which is what makes ten marks read
   as a scale rather than as ten dashes. */
.decade li:nth-child(5n+1)::after { width: calc(var(--R) * .145); }

.decade__now {
  font-size: clamp(21px, 2.8vmin, 40px);
  color: var(--amber-ink);           /* 6.23 */
}
.decade__now::after { height: 2px; background: var(--amber-ink); }

/* ===== CHAT BUTTON ===== */

.chat {
  position: fixed; z-index: 25;
  right: clamp(12px, 2.2vw, 30px); bottom: clamp(14px, 2.4vw, 30px);
  display: flex; align-items: center; gap: 10px;
  text-decoration: none;
  background: var(--wa); color: #fff;
  font-weight: 600; font-size: clamp(13px, 1vw, 16px);
  padding: 9px 20px 9px 9px;
  border-radius: 999px;
  box-shadow: 0 4px 18px rgba(0,0,0,.22);
  transition: background .2s ease;
}
.chat:hover { background: #0f6837; }
.chat img { width: 34px; height: 34px; border-radius: 50%; }

/* ===== RESPONSIVE =====
   What is left of it. This used to be the largest thing in the file: two
   layouts for every panel, a threshold measured off eleven crops, and a
   paragraph of ratios explaining which wash held which words up at which shape.

   Almost none of that survived, because no panel sets type on a photograph any
   more and so no panel's contrast depends on its crop. Vision is one column at
   every width — paper above, picture below — and nothing here reaches it.
   Beliefs turns its strip at 700px, which is a question about how narrow a
   frame can get and is answered on its own threshold further down.

   So this block decides exactly one thing now: whether the values split runs
   side by side or one above the other. The threshold is still 3:2 or 900px,
   which is where it was measured for the old layouts and is still about right
   for this one — 44% of a 390px phone is 170px of picture. */

@media (max-width: 899px), (max-aspect-ratio: 3/2) {
  .panel {
    /* minmax(0, 1fr), not plain 1fr: 1fr floors at the item's min-content, and
       an <img> reports its intrinsic height there — so the picture pushed the
       panel to 892px inside a 760px viewport and the page scrolled for no
       reason. With a zero floor the row is exactly what the copy leaves. */
    grid-template-rows: auto minmax(0, 1fr);
    align-content: stretch;
    align-items: stretch;
    justify-items: stretch;
    padding: 0;                  /* every edge of it moves onto the copy */
  }

  /* The split is a wide-layout idea: 44% of a phone is 170px of picture. Down
     here the two halves go one above the other, which is the same order the
     other panels stack in — page first, picture beneath it. The rail and its
     pearls need no change at all: on the wide layout the thread happens to land
     on the seam between the two halves, but it was never positioned off that
     seam, only off the left edge of the words. */
  .panel--values {
    grid-template-columns: 1fr;
    background: #fbf6ec;
  }
  .panel--values .panel__frame {
    grid-column: 1;
    z-index: 0;
    box-shadow: none;
  }
  .panel--values .panel__copy {
    grid-column: 1;
    align-self: start;
    width: auto;
    max-width: none;
    /* The shared .panel__copy padding below cannot reach this: the wide layout
       sets padding on .panel--values .panel__copy, and a one-class selector does
       not win against a two-class one however late it comes. So the stacked
       padding is restated here rather than inherited — the same trap the values
       column's width fell into above. */
    padding: clamp(72px, 12vh, 110px) var(--pad) clamp(26px, 4vh, 44px);
  }

  .panel__copy {
    grid-row: 1;
    max-width: none;
    /* All four paddings sit on this block rather than on the section, so the
       gradient starts at the very top of the panel. Split across the two, it
       left a seam above the heading. */
    padding: clamp(72px, 12vh, 110px) var(--pad) clamp(22px, 4vh, 40px);
  }

  .panel__frame {
    position: relative; inset: auto; z-index: 0;
    grid-row: 2;
    min-height: 0;               /* so the row is the remainder, nothing more */
    /* Belt and braces on the join: 34px of cross-fade absorbs whatever the
       sampled colour does not. */
    -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 34px);
            mask-image: linear-gradient(180deg, transparent 0, #000 34px);
  }

  /* Vision is not here. It is this shape at every width, so its rules are all in
     its own section and there is nothing to switch. */

  /* No gradient to sample and match any more. The page is one flat colour, the
     panel behind the picture is the same colour, and the 34px mask at the top of
     the frame fades the photograph onto it — which is what the gradient was
     approximating in the first place. */
  .panel--values .panel__copy { background: none; }
  .panel--values .panel__art  { object-position: 36% 70%; }   /* the pearls, not the fan above them */

  /* There is no vertical join to string the pearls on any more — the seam is
     horizontal now and it is under the words, not beside them — so they come
     back into the flow and sit above their own names' worth of words. The
     three sizes stay: they are the photograph's own arrangement, not a
     property of the wide layout. */
  .panel--values .panel__copy { --pearl: clamp(96px, 26vw, 168px); }
  .panel--values .panel__title { margin-left: 0; }
  /* Block, not grid: the pearl is in the flow again and the three words have to
     be able to wrap under it. Left as a row of columns they ran off the side of
     a 390px panel — Trustworthy and Empower were both cut in half. */
  .values__group {
    display: block;
    padding-left: 0;
    min-height: 0;
  }
  .values dt {
    position: static;
    transform: none;
    margin-bottom: .5em;
  }

  /* Beliefs still does not stack the way the other two do — there is no single
     photograph under it to match a gradient to, and now there is no photograph
     under it at all. All that is left to hand back is the panel's own box: the
     grid rows the stacked layout imposes, and the inset the strip does not
     want. Which axis the strip runs on is decided further down, on its own
     threshold, because that is a question about the strip and not about whether
     the other two panels have stacked. */
  .panel--beliefs {
    display: grid;
    grid-template-rows: none;
    align-content: center;
    align-items: center;
    justify-items: stretch;
    padding-block: clamp(84px, 14vh, 150px);
    padding-inline: var(--pad);
  }
  .panel--beliefs .panel__copy {
    width: auto; max-width: none;
    grid-row: auto;
    padding: 0;
    background: none;
  }
}

/* Four columns is unusable below about 700px — an idle frame there is under
   100px wide and its caption breaks to four lines. So the strip turns: four
   rows, the accordion opening downwards, everything else about the panel
   unchanged. That is the return on having built it out of frames rather than
   out of a backdrop and a list; the whole switch is one axis. */
@media (max-width: 699px) {
  /* Four plates across a 390px panel is 84px each, under half the resolution the
     files have, and "Chief Digital Innovator" has nothing to set in. Two by two
     instead: the plates go back to about their own width and the roles get a
     measure. */
  .leaders { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Four cards on a staggered baseline is a rhythm; two rows of two on one is
     a misalignment. The offsets go and the pairs sit level. */
  .leader:nth-child(2), .leader:nth-child(3), .leader:nth-child(4) { margin-top: 0; }

  .sheet {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(4, 1fr);
    height: clamp(430px, 68vh, 700px);
    transition: grid-template-rows var(--open) var(--ease);
  }
  :where(#b1:checked ~ .panel__copy) .sheet { grid-template-columns: 1fr; grid-template-rows: 2.2fr 1fr 1fr 1fr; }
  :where(#b2:checked ~ .panel__copy) .sheet { grid-template-columns: 1fr; grid-template-rows: 1fr 2.2fr 1fr 1fr; }
  :where(#b3:checked ~ .panel__copy) .sheet { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr 2.2fr 1fr; }
  :where(#b4:checked ~ .panel__copy) .sheet { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr 1fr 2.2fr; }
}

/* The turned strip, under the pointer. A 699px window with a mouse in it is a
   real thing — a narrow desktop window, not only a phone — and without this the
   frames would light up on hover and refuse to open. */
@media (hover: hover) and (pointer: fine) and (max-width: 699px) {
  .sheet:has(.sheet__frame:nth-child(1) label:hover) { grid-template-columns: 1fr; grid-template-rows: 2.2fr 1fr 1fr 1fr; }
  .sheet:has(.sheet__frame:nth-child(2) label:hover) { grid-template-columns: 1fr; grid-template-rows: 1fr 2.2fr 1fr 1fr; }
  .sheet:has(.sheet__frame:nth-child(3) label:hover) { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr 2.2fr 1fr; }
  .sheet:has(.sheet__frame:nth-child(4) label:hover) { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr 1fr 2.2fr; }
}

/* Two columns of prose, and a ruler beside a column of prose. Below 820px
   neither has a measure worth reading, so both go to one column — and the ruler
   turns rather than stacking, because ten years down a phone is ten rows of
   nothing. Same object, seen from the other side. */
/* The rail is four cards wide at their own resolution — 4x250 and three 34px
   gaps, 1102px — and the paragraph wants 230 at the least. Add the panel's own
   inset and the gap between them and two columns need about 1700px of viewport
   before they stop fighting. 1099 was measured off the layout instead of off
   the arithmetic and it was wrong twice over: at 834x1112 the paragraph took
   its 360 and the rail was handed 314, which put the fourth leader off the side
   of the panel, and at 1280x580 — a 1920 laptop at 150% scaling, which is what
   a great many of them are — the rail kept its 1102 and pushed the paragraph
   off the right edge instead.

   Below the threshold the paragraph goes above and the rail takes the width,
   shrinking its columns rather than losing one. The minmax(0, max-content) on
   the track above is the belt to this braces: it means no width can push
   anything off the panel even if this number is wrong again. */
@media (max-width: 1699px) {
  .leaders__body {
    grid-template-columns: 1fr;
    gap: clamp(22px, 4vh, 40px);
  }
  .leaders__intro { order: -1; max-width: 66ch; }
}

@media (max-width: 420px) {
  .chat span { display: none; }   /* icon only, so the button stops crowding the line */
  .chat { padding: 9px; }
}

/* ===== SHORT VIEWPORTS =====
   A landscape phone has the width for the side-by-side layout but nothing like
   the height for its vertical rhythm. */
@media (max-height: 620px) {
  /* Only the vertical rhythm gives way. Letting a panel collapse to auto height
     was worse: with the picture out of flow there was nothing left to give the
     frame a height and the artwork disappeared entirely. */
  .panel { padding-block: 0; }
  .panel__copy { padding-block: 58px 14px; }
  /* Both redesigned panels set padding on a two-class selector, so the shared
     rule above cannot reach either of them however late it comes. Restated at
     matching specificity — without this a landscape phone puts the We Value
     heading 72px down a 420px screen and the Our Beliefs heading flush against
     the top edge of the panel. */
  .panel--values .panel__copy  { padding-block: 58px 14px; }
  .panel--beliefs .panel__copy { padding-block: 46px 12px; }

  /* Twelve stacked lines is a column of type taller than a 420px screen: at
     740x420 the old layout filled the whole panel, the picture was squeezed to
     zero height and the last few values ran underneath the chat button. Three
     columns is the normal layout now and 740 is over the 620 threshold, so all
     that is left to do here is tighten the rhythm. */
  .values { margin-top: clamp(10px, 2vh, 18px); }
  /* Three pearls sized off the width of a landscape phone is 190px each, which
     is more than a 420px panel has to give three of. Sized off the height they
     come out at 64px, and a 64px pearl sets its own name at 9px — so here the
     name comes back out of the pearl and the pearl goes back to being a bead
     beside it, which is what this panel did before the pearls grew. It is the
     one size at which the idea does not fit, and saying so in ten lines is
     better than shipping a name nobody can read. */
  .panel--values .panel__copy { --bead: clamp(11px, 2.6vh, 18px); }
  .values__group { padding-left: calc(var(--bead) * 1.9); }
  .values dt {
    position: relative;
    width: auto; height: auto;
    display: block;
    border-radius: 0;
    background: none;
    box-shadow: none;
    text-align: left;
    font-size: clamp(17px, 3.4vh, 26px);
    color: var(--sand-ink);            /* 6.21 on the page */
    margin-bottom: .18em;
  }
  .values dt::before {
    content: "";
    position: absolute;
    left: calc(var(--bead) * -1.9);
    top: .58em;
    width: var(--bead);
    height: var(--bead);
    transform: translateY(-50%);
    border-radius: 50%;
    background: radial-gradient(circle at 34% 28%,
      #ffffff 0%, #fffaf1 13%, #f6e9d7 45%, #e8d5bd 72%, #c9ad8b 90%, #a58a79 100%);
    box-shadow: inset -1px -1px 2px rgba(120,88,50,.34), 0 1px 3px rgba(96,62,25,.28);
  }
  .values dd { line-height: 1.4; }
  .values__group + .values__group { margin-top: clamp(12px, 2.4vh, 22px); }

  /* The strip's 54vh is a proportion of a tall viewport. On a 420px landscape
     phone the same proportion is 227px, but the clamp's 300px floor would hold
     it at 300 and .panel's overflow:hidden would cut the bottom off four frames
     rather than shorten them. A lower floor here is the whole fix — above 700px
     wide the strip is still four columns at this height, which is the layout a
     landscape phone actually wants. */
  .sheet { height: clamp(190px, 56vh, 330px); margin-top: clamp(10px, 2vh, 20px); }

  /* A 5:6 card plus its name is taller than a 420px landscape phone, and the
     stagger adds another 70px on top of that. The photograph gives up the
     height rather than the panel giving up a card — a wider crop still has the
     face in it, which is what object-position is anchored on — and the rail
     goes back to one baseline. */
  .panel--leaders .panel__copy { padding-block: 44px 12px; }
  .panel--leaders .panel__title { margin-bottom: clamp(12px, 2.6vh, 26px); }
  .leader__shot { aspect-ratio: 16 / 11; }
  .leader__mark { font-size: clamp(34px, 9vh, 60px); }
  .leader:nth-child(2), .leader:nth-child(3), .leader:nth-child(4) { margin-top: 0; }

  /* Nothing here shortens the dial: --R is .776 of the viewport height already,
     so the scale and the collage shrink with the panel on their own. This used
     to be where the collage was deleted outright — a 1280x583 window hid it and
     left the copy in a 435px column with 845px of empty amber beside it, which
     is the layout in the screenshot that started this rewrite. The panel it is
     hidden from no longer exists.

     Only the shared padding has to go, and for the usual reason: this panel
     centres its copy in the opening instead of sitting it under a rule. */
  .panel--life .panel__copy { padding-block: 0; }
  .panel--life .panel__copy p { line-height: 1.55; }
}

/* ===== LIFE @ EASTON, STACKED =====
   The dial needs a panel wider than the picture and no taller than 5:4. The
   opening is a disc as wide as the collage itself, so a narrow or a portrait
   panel has room for the opening or for a column of type but never for both —
   at 834x1112 the rim lands across the middle of the paragraph.

   Below that the collage goes to the top of the panel whole, and the decade
   lies flat under the words: the same list, seen from the other side. Nothing
   is cropped here either. A band across the top was tried first and it is what
   a cover crop cannot do to this file — the picture is a ring segment, so any
   box wider than about 5:2 fills with the opening rather than with faces, and
   at 834 wide a crop tight enough to be all photographs is a 2.3x enlargement
   of a 900px master. The whole shape at a size it can hold is the honest
   version of the same idea, and every offset below is the geometry from the
   dial with two numbers changed: the centre moves so the picture sits in the
   middle of the panel, and the stage is exactly as tall as the picture.

   It sits after the short-viewport block on purpose. That block zeroes
   .panel's padding, and here the picture is held up by padding — restated on
   two classes for the same reason We Value and Our Beliefs restate theirs. */
@media (max-width: 999px), (max-aspect-ratio: 5/4) {
  .panel.panel--life {
    /* Sized off both axes and capped under the master's own width, so the
       collage is always being reduced rather than enlarged here. The height
       term is the one that matters on a landscape phone: the picture is 1.94
       radii tall, so a third of the viewport height buys two thirds of the
       screen and leaves the heading nothing. .23 keeps it under half. */
    --R: min(44vw, 23vh, 300px);
    --band: calc(var(--R) * 1.93624);            /* 990 / 511.3 — the picture, exactly */
    --pivot-x: calc(50% + var(--R) * .91947);    /* half the picture's own width, so it centres */
    --pivot-y: calc(var(--R) * .46508);
    display: grid;
    align-content: start;
    padding: calc(var(--band) + clamp(26px, 5vh, 58px)) var(--gutter) clamp(40px, 7vh, 90px);
  }

  /* As tall as the picture and no taller: there is nothing to clip. */
  .life__art { inset: 0 0 auto 0; height: var(--band); }

  .panel--life .panel__copy { margin-left: 0; }

  /* Back in flow under the copy, as a rule with the years hanging off it. The
     two offsets have to be unset by hand — the list is positioned either way,
     and left at the pivot they would push the whole scale off the panel.

     Five to a row rather than a flex line that wraps where it runs out: ten
     years at a readable size are wider than a phone, and a wrapped flex line
     leaves the second row with no rule over it and the widow at whatever column
     the first row happened to end on. The rule is carried by each year instead
     of by the list, so it is continuous across a row because the cells abut,
     and every row has one. The fade goes into the border colour, which is where
     a per-year value can live; the type stays one ink. */
  .decade {
    position: relative;
    left: auto; top: auto;
    width: auto; height: auto;
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    align-content: start;
    row-gap: clamp(18px, 3.4vh, 34px);
    margin-top: clamp(26px, 5vh, 46px);
    --rail: clamp(14px, 4vw, 28px);
  }
  .decade li {
    position: relative;
    transform: none;
    padding-top: var(--rail);
    border-top: 1px solid rgba(111,63,24, calc(.55 - (var(--i) - 1) * .042));
    text-align: center;
  }
  .decade li::after {
    right: auto; left: 50%;
    top: 0;
    width: 1px;
    height: clamp(8px, 2.2vw, 14px);
    margin: 0;
    transform: translateX(-50%);
  }
  .decade li:nth-child(5n+1)::after { width: 1px; height: clamp(14px, 3.6vw, 24px); }
  /* The marked year gets a dot centred on the rule instead of a tick under it. */
  .decade__now::after {
    width:  clamp(9px, 2.4vw, 14px);
    height: clamp(9px, 2.4vw, 14px);
    border-radius: 50%;
    transform: translate(-50%, -50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat { transition: none; }
  /* The storks stop where the photograph has them. The resting transform is the
     identity, so this is not a second layout or a still frame chosen out of the
     cycle — it is Paravai-1.jpg, which is what the five files add back up to. */
  .stork { animation: none; translate: none; rotate: none; transition: none; }
  /* The strip opening, the chosen frame coming back to colour and the ring
     landing on it are all state changes a reader can ask not to have animated.
     Every one of them still happens — instantly. Nothing here is gated on a
     transition finishing, which is why turning them all off leaves the panel
     working rather than stuck. */
  .sheet,
  .sheet img,
  .sheet label::before,
  .sheet__cap { transition: none; }
}

@media print {
  .panel { min-height: auto; }
  /* A black panel prints as a full page of ink and the four names print as
     white on white. The ground goes, and with it the one thing this panel's
     colours depend on: #f2415f, #dfa63a, #22c4d6 and #5b9bf0 are legible on
     #0b0d0e and are 3.22, 1.90, 1.85 and 2.49 on paper, which is the live
     site's own mistake and not one to reprint. On paper the four names are ink
     and the roles are grey. */
  .panel--leaders { background: none; }
  .leader { box-shadow: none; }
  .leader:nth-child(2), .leader:nth-child(3), .leader:nth-child(4) { margin-top: 0; }
  .leader label { transform: none; }
  .leader__shot, .leader__mark { display: none; }
  .leader__body { padding: 0; }
  .leader__name { color: var(--ink-print, #101416); }
  .leader__role { color: #4d5457; }
  .leaders__intro { color: #262b2e; }
  /* The amber field is the one background on this page that is not standing in
     for a photograph, and it still costs a full page of ink to say nothing. The
     collage goes with every other image, and the geometry that was placing it
     goes with it — the copy is a column of type and nothing else. */
  .panel--life { background: none; display: block; padding: 0; }
  .life__art { display: none; }
  .panel--life .panel__copy { padding: 0; margin-left: 0; }
  /* The dial is a set of polar transforms about a centre the picture is not on
     the page to define any more. On paper the decade is a list of years. */
  .decade { position: static; display: flex; flex-wrap: wrap; gap: 14px; }
  .decade li { position: static; transform: none; }
  .decade li::after { display: none; }
  .panel__art, .chat { display: none; }
  /* Vision's paper is a gradient sampled to meet a photograph that is not being
     printed, so it prints as a grey wash under the type for no reason. */
  .panel--vision { display: block; background: none; }
  .panel--vision .panel__copy { background: none; padding: 0; }
  .panel--vision .panel__frame { display: none; }
  /* Values is a picture beside a page. On paper the picture is dropped with
     every other .panel image, so the column it occupied would print as 44% of
     the sheet left blank. */
  .panel--values {
    display: block;
    background: none;
  }
  .panel--values .panel__frame { display: none; }
  .panel--values .panel__copy { padding: 0; }
  /* A drawn pearl is a gradient, and a gradient prints as a grey disc with a
     name in it. The three go back to being three names, which is what they say
     on paper. */
  .panel--values .panel__title { margin-left: 0; }
  .values__group { padding-left: 0; min-height: 0; }
  .values dt {
    position: static;
    transform: none;
    width: auto; height: auto;
    display: block;
    border-radius: 0;
    background: none;
    box-shadow: none;
    font-size: 15pt;
    text-align: left;
    color: var(--sand-ink);
    margin-bottom: .2em;
  }
  /* Beliefs is four photographs on a dark sheet, and neither of those survives
     paper: the images are dropped with every other .panel image above, and the
     sheet's white heading would print white on white. The four statements are
     what is left, so they are set as a list in the body ink and the strip stops
     being a fixed height it no longer needs. */
  .panel--beliefs { background: none; }
  .panel--beliefs .panel__title { color: var(--sky-body); }
  .sheet {
    display: block;
    height: auto;
  }
  .sheet img,
  .sheet label::after { display: none; }
  .sheet label {
    height: auto;
    background: none;
    padding-left: 2.4em;
  }
  .sheet label::before { color: rgba(0,0,0,.55); background: none; }
  .sheet__cap {
    position: static;
    display: block;
    padding: .18em 0;
    background: none;
    color: var(--sky-body);
  }
}
