/* Principle cards — the learning principles as a card deck.
 *
 * Used only by _includes/bands/principle_cards.html (which links this file),
 * so everything is namespaced under .principle-cards. Card format after the
 * Waters Center "Habits of a Systems Thinker" cards: label on the front;
 * claim + assumption + narrative on the flip side.
 *
 * The cards are HEXAGONS: each front is clipped to a pointy-top hexagon
 * (aspect 866:1000, so the clip percentages give a regular hex) with the
 * Tsuro-board art full-bleed behind an overlaid label. Offset rows pull up
 * into the hexagons' notches (negative top margins) to interlock the
 * honeycomb.
 *
 * The flip side opens as a LIGHTBOX — a native <dialog> per card, one large
 * centered black card over the dimmed deck. The deck used to 3D-flip each
 * card in place; that died with the 6-wide widescreen comb (backs bigger
 * than the hexes + negative comb margins = overlapping mess). The flip era's
 * Chromium traps (clip-path vs backface-visibility, filter-after-clip) are
 * recorded in the project memory should in-place flipping ever return.
 *
 * BROWSER SUPPORT (2026-09-06): the deck is meant to render correctly on
 * anything from ~2019 on (Safari/iOS 13, Chrome 80, Firefox ESR 91,
 * Samsung Internet 12), not just current browsers. So the layout avoids
 * the 2021-23 features it used to lean on — container-query units,
 * aspect-ratio, inset, min()/clamp(), <dialog> as the only modal — and
 * uses percentage margins/padding on grid items (which resolve against the
 * grid AREA's inline size, i.e. the card width, per css-grid-1 §6) for the
 * geometry instead. Where a newer feature is still used it is additive:
 * the older declaration comes first and the newer one overrides it.
 * Autoprefixer (jekyll-autoprefixer-re, "last 2 versions") adds the
 * -webkit- prefixes at build time; nothing here relies on hand prefixes.
 */

/* ONE SIZE INPUT. Everything about a hexagon — its seat in the ring, its
 * label, the foot that label sits on, the pull-up of a fallback row — is a
 * proportion of --pc-w, the way the tile deck is a proportion of --st-w.
 *
 * It replaced a type ladder: .pc-label used to be set five times, at 1.45rem
 * (base), 1.02rem (>=1280), 0.95rem (<=639), 0.8rem (the in-page deck) and
 * 1.05rem (a slide) — five ABSOLUTE sizes on a card whose width was never
 * absolute, each one added to patch the one before. Three of the five were
 * media queries, which a deck reads against the real viewport rather than
 * against its own 1920 canvas; that is a whole class of bug this deletes. */
.principle-cards {
  --pc-gold: var(--anu-gold);
  --pc-gold-deep: #96670a; /* 4.9:1 on white — AA for the small mono labels */
  --pc-ink: #141414;
  --pc-w: 148px;
  --pc-gap: 16px;
  /* THE RIBBON'S WEIGHT, in the board sprite's units, exactly as the map sets
   * it (societie-tiles.css). The board is one cell scaled x4 onto the card,
   * so the sprite's own 5 and 8 would land as a band a fifth of the card
   * wide. cb, 2026-09-17: "these tiles don't match the tsuro rules - one
   * connection at the midpoint of the vertice" — the cards were a
   * many-celled texture until then, and set neither. */
  --pt-line: 2;
  --pt-casing: 3.2;
  /* Centre-to-centre along a row of the hex lattice. */
  --pc-pitch: calc(var(--pc-w) + var(--pc-gap));
  /* The one number the card and the hub share, so their labels cannot drift
   * apart: how far the title block sits off the hexagon's lower point. */
  --pc-label-foot: calc(var(--pc-w) * 0.09);
}

/* ⚠️ NO TOOLBAR AND NO COUNT. cb, 2026-09-17, of this band and the map
 * together: "remove the title XX cards", "position the 'Full screen' button
 * to be inside the active window space". The bar is gone; the button is the
 * only chrome left and it now sits ON the field.
 *
 * Top RIGHT rather than top left, in both bands: the field is fitted to the
 * box with PAD of air all round, so the corners are the emptiest part of the
 * view — and the right-hand one is the corner a docked panel is least often
 * under, since the panel goes to the side away from the card being read and
 * most of the reading starts on the left. */
.principle-cards .pc-fullscreen {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 3;
  /* Paper, not `none`: it is over hexagons now, and an outlined button with
   * the field showing through it stops being readable the moment a cluster
   * drifts under it. The rgba() triple is this file's documented exception
   * to "never write a hex" — a custom property cannot go inside rgba(). */
  background: rgba(251, 249, 245, 0.92);
  font-family: "Roboto Mono", monospace;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--pc-ink);
  border: 1.5px solid var(--pc-ink);
  border-radius: 0;
  padding: 10px 18px;
  cursor: pointer;
  -webkit-box-shadow: none;
          box-shadow: none;
}

.principle-cards .pc-fullscreen:hover,
.principle-cards .pc-fullscreen:focus {
  background: var(--pc-ink);
  color: var(--pc-gold);
}

.principle-cards .pc-fullscreen:focus-visible {
  outline: 3px solid var(--pc-gold);
  outline-offset: 3px;
}

/* Fullscreen mode: the whole deck div goes fullscreen (toolbar, field and
 * the lightbox dialogs all inside it), on the site's paper rather than the
 * UA's black. A roomier VIEW and nothing more — the cards are live either
 * way, which they were not before 2026-09-16.
 *
 * ⚠️ This is the SECOND of the two layers, not the mechanism. .pc-expanded
 * above pins the band to the viewport and works everywhere, including the
 * iPhones that have no Fullscreen API at all; the real API is layered on top
 * where it exists, only to take the browser's own chrome. The two are always
 * applied together, so this rule needs to carry nothing the other one
 * already does — it only has to stop the UA painting its black behind a
 * transparent element in the top layer. */
.principle-cards:-webkit-full-screen {
  background: var(--colour-surface, #fbf9f5);
}
.principle-cards:-ms-fullscreen {
  background: var(--colour-surface, #fbf9f5);
}
.principle-cards:fullscreen {
  background: var(--colour-surface, #fbf9f5);
}

/* The card's focus indicator can't be an outline — outlines trace the
 * button's rectangular box, not the hexagon. Stacked drop-shadows on the
 * front build an accent ring that follows the clip. */
.principle-cards .pc-card:focus-visible {
  outline: none;
}

.principle-cards .pc-card:focus-visible .pc-front {
  -webkit-filter: drop-shadow(0 0 1.5px var(--pc-gold)) drop-shadow(0 0 1.5px var(--pc-gold))
    drop-shadow(0 0 2px var(--pc-gold));
          filter: drop-shadow(0 0 1.5px var(--pc-gold)) drop-shadow(0 0 1.5px var(--pc-gold))
    drop-shadow(0 0 2px var(--pc-gold));
}

.principle-cards {
  --pc-hex: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* ── The shape: four family clusters ─────────────────────────────────────
 * Each family is a ring of its principles around a hub hexagon carrying the
 * family's name, ported from the tile deck's cluster layout. It replaced a
 * honeycomb whose family rows were an nth-child CYCLE — 9n+1..9n+5 on one
 * row, 9n+6..9n+9 on the next — which was the families only while the
 * counts stayed 5/4/5/4 IN THAT ORDER. The data is SharePoint-owned and
 * staff edit it, so a nineteenth principle silently regrouped the colour
 * bands. A ring is keyed to nothing: a new row takes the next seat.
 *
 * How many clusters sit across was flex-wrap until 2026-09-17 — two in the
 * prose column, four on a 1920 slide, one on a phone. It is now neither
 * flex nor a breakpoint: the clusters have real coordinates on one field and
 * a camera fits that field to whatever box it has, which is the same answer
 * at every width. See THE FIELD in bands/principle_cards.html. */
.principle-cards .pc-grid {
  margin-top: 2rem;
}

/* ⚠️ A CLUSTER IS NOT A BOX ANY MORE. Until 2026-09-17 it was: a
 * 2*pitch + w by 1.732*pitch + 1.1547w rectangle holding six seats measured
 * from its own centre, laid out by flex and then by --ci/--ri. Since the
 * field became one placed canvas (see THE FIELD in bands/principle_cards.html)
 * every hexagon carries a WORLD cell instead, and this element survives only
 * to carry role="group" and the family's name for a screen reader.
 *
 * So it is deliberately size-less and unpositioned: its cells are absolute
 * against .pc-canvas, which is the positioned ancestor. `display: contents`
 * would say this more directly but drops the element — and its role — out of
 * the accessibility tree in the Safari versions this deck still supports. */
.principle-cards .pc-cluster {
  position: static;
  display: block;
  width: 0;
  height: 0;
  margin: 0;
}

/* Axial to pixels, the one conversion the whole layout rests on, and now
 * character-for-character the map's (.st-cell in societie-tiles.css): the
 * band hands down xk = 2q + r already shifted to the field's own origin, so
 * a column step is half a pitch of xk and a row step is 0.866 of a pitch.
 * Keeping the two rules identical is the point — cb: "let's make the two
 * artefacts feel similar in layout, size - don't let this drift." */
.principle-cards .pc-cell {
  position: absolute;
  width: var(--pc-w);
  height: calc(1.1547 * var(--pc-w));
  left: calc(var(--xk) * var(--pc-pitch) / 2);
  top: calc(var(--r2) * 0.866 * var(--pc-pitch));
}

/* A <button> is shrink-to-fit, so inside an absolutely-positioned seat it
 * would size itself to its label and every short-labelled card would come
 * out a different hexagon. The seat owns the width; the card takes all of
 * it and lets the 115.473% spacer set the height. */
.principle-cards .pc-cell > .pc-card,
.principle-cards .pc-cell > .pc-hub {
  width: 100%;
}

/* Interlocked hexes overlap; a paper card reads over the hub rather than
 * under it, and the card in use comes over everything. */
.principle-cards .pc-cell-hub {
  z-index: 0;
}

/* The hub became a real <button> when it became a waypoint (it flies the
 * camera to its own family), so it has a UA appearance to unset. Everything
 * visible about it still comes from .pc-hub-front underneath. */
.principle-cards .pc-hub {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
  -webkit-box-shadow: none;
          box-shadow: none;
  display: block;
}

/* An outline would trace the button's rectangle, not the hexagon; the ring
 * is drawn on the front, exactly as the cards do it. */
.principle-cards .pc-hub:focus-visible {
  outline: none;
}

/* ── The viewport and the camera ───────────────────────
 * The field is FIXED: two clusters across, as many rows as the families
 * need, at one card size everywhere. What changes with the screen is the
 * CAMERA (assets/js/hex-camera.js) — a transform on the canvas that fits the
 * field into whatever box the viewport has.
 *
 * It replaced a wrapping flex row and the ladder of media queries that
 * propped it up (--pc-w at 148 / 128 / 112 / 96, plus a negative gutter on a
 * phone). Each step existed to stop the clusters wrapping into a tower at
 * some width, and each one was found the hard way after the layout shipped:
 * two across needed 1011px and the prose column is 908 on a 1024 laptop, so
 * the band went from ~950px tall to 1900 with nothing to warn anybody. A
 * camera has no widths to get wrong, and it is what the tile map opposite it
 * on /societie/introduction/ has always used — cb, 2026-09-17: "let's make
 * the two artefacts feel similar in layout, size - don't let this drift."
 *
 * ⚠️ The card size is now a RESOLUTION, not a size. Every label, halo and
 * seat is a proportion of --pc-w and the whole canvas is then scaled, so
 * changing --pc-w zooms the field rather than reflowing it. That is why the
 * media queries could go, and why no new one should arrive.
 */
.principle-cards .pc-viewport {
  position: relative;
  overflow: hidden;
  width: 100%;
  margin-top: 2rem;
  /* A LENGTH, not a vh: inside reveal, vh resolves against the real window
   * while the slide is laid out on a 1920x1080 canvas, so a viewport in vh
   * comes out about a third of the height it looks like it asked for and the
   * whole-field view clamps at minimum zoom. Same trap, same answer, as
   * --st-map-h in societie-tiles.css. The default and the cap are that
   * rule's own 620px / 88vh, so the two bands on /societie/introduction/
   * open at the same size. */
  height: var(--pc-map-h, 620px);
  max-height: 88vh;
  /* A hairline of paper, so the field reads as something you are looking
   * INTO rather than as cards scattered on the page. */
  background: rgba(20, 20, 20, 0.02);
  border-radius: 10px;
  cursor: -webkit-grab;
  cursor: grab;
  -ms-touch-action: none;
      touch-action: none; /* the pointer handlers own panning, not the browser */
}

.principle-cards .pc-viewport.pc-dragging {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

.principle-cards .pc-canvas {
  position: absolute;
  top: 0;
  left: 0;
  margin-top: 0;
  -webkit-transform-origin: 0 0;
          transform-origin: 0 0;
}

/* The field's own size, which is what the camera fits: the BOUNDS of what is
 * placed, plus one hexagon, because --xk and --r2 give a cell's top-left
 * corner. Same two lines as .st-map in societie-tiles.css. A placement moved
 * in /societie/introduction/principles/edit/ changes these spans, so the
 * field grows and shrinks around the arrangement rather than around a grid
 * of fixed cluster boxes. */
.principle-cards .pc-canvas.pc-clusters {
  display: block;
  /* ⚠️ NO GAP ON THE PLACED FIELD, and the same decision societie-tiles.css
   * makes on .st-map for the same reason. cb, 2026-09-17: "can we also lay
   * this out so that the hexes touch, like with the introduction" — the
   * introduction being the tile map on the same page, which is one
   * continuous honeycomb rather than a set of cards with air between them.
   *
   * With the gap at zero the pitch IS the card width, so the axial rule
   * below tessellates exactly: every hexagon meets its six neighbours edge
   * to edge and the four families read as one field. It belongs here, on the
   * canvas, and not on .principle-cards: the honeycomb ROWS fallback is a
   * comb of separate cards and keeps the 16px, exactly as the map's cluster
   * and path layouts keep their 12px.
   *
   * It is also what lets the ARTWORK run on. Since 2026-09-17 every card's
   * board is ONE Tsuro cell the size of the card (generate_principle_art.py,
   * GEOMETRY), so each of its six edges carries exactly one ribbon, at the
   * midpoint — and a midpoint belongs to both hexagons that share the edge,
   * so with no gap every ribbon crosses the seam into the next card. With a
   * gap they would stop short by it, which is why the rows fallback reads
   * as separate cards. */
  --pc-gap: 0px;
  --pc-pitch: calc(var(--pc-w) + var(--pc-gap));
  width: calc(var(--pc-spanxk) * var(--pc-pitch) / 2 + var(--pc-w));
  height: calc(
    var(--pc-spanr) * 0.866 * var(--pc-pitch) + 1.1547 * var(--pc-w)
  );
}

/* The fallback rows keep their own flow; the canvas just has to stop
 * shrink-to-fit from squeezing them against the viewport's width. */
.principle-cards .pc-canvas.pc-rows {
  width: -webkit-max-content;
  width: -moz-max-content;
  width: max-content;
}

/* ── Waypoints ──────────────────────────────────────
 * The family buttons under the field, and the same object as the tile map's
 * .st-waypoint — deliberately the same shape, size and behaviour, because
 * the two bands now sit on one page and a reader should not have to learn
 * them twice. They are also the keyboard and screen-reader route into the
 * field: a reader who cannot drag can still reach a family. */
.principle-cards .pc-waypoints {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-wrap: wrap;
      flex-wrap: wrap;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  margin: 14px 0 0;
}

/* The how-to line under the waypoints (the `hint=` include param). */
.principle-cards .pc-howto {
  margin: 10px 0 0;
  text-align: center;
  font-size: 0.85rem;
  color: var(--colour-text-muted);
}

.principle-cards .pc-waypoint {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  font-family: "Roboto Mono", monospace;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--pc-ink);
  background: none;
  border: 1.5px solid var(--pc-ink);
  border-radius: 999px;
  -webkit-box-shadow: none;
          box-shadow: none;
  padding: 7px 15px;
  /* Not flex `gap`: it is Safari 14.1, and this deck renders back to 13. */
  margin: 0 4px 8px;
  cursor: pointer;
  line-height: 1;
}

.principle-cards .pc-waypoint[aria-pressed="true"] {
  background: var(--pc-ink);
  color: var(--pc-gold);
}

.principle-cards .pc-waypoint:focus-visible {
  outline: 3px solid var(--pc-gold);
  outline-offset: 2px;
}

/* ── Expand in place ────────────────────────────────
 * ⚠️ This, and not :fullscreen, is the mechanism. iOS Safari has no
 * Fullscreen API outside <video>, so the old button was `hidden` on every
 * iPhone — missing from the one device whose screen makes it worth pressing,
 * and cb's report was a phone report. A pinned overlay works everywhere; the
 * real API is asked for on top of it where it exists, to take the browser's
 * own chrome as well.
 *
 * Longhand offsets, not `inset`: the floor here is Safari 13. */
.principle-cards.pc-expanded {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1200;
  margin: 0;
  padding: 1rem 1.25rem 1.25rem;
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
  background: var(--colour-surface, #fbf9f5);
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
}

/* The viewport takes the height the toolbar and waypoints leave, rather than
 * its own fixed --pc-map-h: the point of expanding is the room. */
.principle-cards.pc-expanded .pc-viewport {
  -webkit-box-flex: 1;
      -ms-flex: 1 1 auto;
          flex: 1 1 auto;
  height: auto;
  max-height: none;
  min-height: 0;
  margin-top: 1rem;
}

/* The page behind must not scroll under the overlay: on a phone the momentum
 * of the scroll already in flight carries on and the reader lands somewhere
 * else when they close it. Set by hex-camera.js on <html>. */
.hex-expanded-lock,
.hex-expanded-lock body {
  overflow: hidden;
}

/* ── The fallback shape: family rows ─────────────────────────────────────
 * A ring holds six. A family bigger than that sends the WHOLE deck back to
 * the honeycomb rows it used to be — real elements, one per family, so the
 * families are still the families. The band decides which rows are pushed;
 * the arithmetic is the tile comb's, from the same two constants. */
.principle-cards .pc-grid.pc-rows .pc-row {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  /* Rows overlap, so the one BELOW must paint over the one above for the
   * notches to read as notches rather than as a seam. */
  -webkit-box-align: start;
      -ms-flex-align: start;
          align-items: flex-start;
}

/* A row rises by the hexagon's point height (0.28868 of its width) less
 * 0.866x the gap, because rows meet along the slanted edges and that easing
 * is what makes the diagonal edge-to-edge distance equal the gap between
 * vertical edges. */
.principle-cards .pc-grid.pc-rows .pc-row + .pc-row {
  margin-top: calc(-0.28868 * var(--pc-w) + 0.866 * var(--pc-gap));
}

/* Two centred rows whose lengths differ by an ODD number interlock on their
 * own; any other pair sits point-on-point until one is pushed half a pitch. */
.principle-cards .pc-grid.pc-rows .pc-row-shift {
  -webkit-transform: translateX(calc(var(--pc-pitch) / 2));
          transform: translateX(calc(var(--pc-pitch) / 2));
}

.principle-cards .pc-grid.pc-rows .pc-card {
  width: var(--pc-w);
  /* A flex item shrinks by default; a comb whose last row is squeezed by a
   * pixel stops tessellating. */
  -webkit-box-flex: 0;
      -ms-flex: 0 0 auto;
          flex: 0 0 auto;
  margin: 0 calc(var(--pc-gap) / 2);
}

/* ── The cards (fronts) ─────────────────────────────────────────────── */

.principle-cards .pc-card {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  /* The theme gives <button> white-space: nowrap, which inherits into every
   * span in the card and clips the label at the card edge. */
  white-space: normal;
  /* The theme shadows <button> boxes; a rectangular glow around a hexagonal
   * card gives the square away, so the shadow moves to a drop-shadow filter
   * on the front, which follows the clip-path alpha instead of the box. */
  -webkit-box-shadow: none;
          box-shadow: none;
  display: grid;
  position: relative;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* The card's 866:1000 aspect, without aspect-ratio (Safari <15, Chrome
 * <88): an empty spacer whose top padding is 1000/866 of the card width
 * (percentage padding resolves against the grid area's inline size) sits
 * in the same grid cell as the front, which stretches to match it. */
.principle-cards .pc-card::before {
  content: "";
  grid-area: 1 / 1;
  padding-top: 115.473%;
}

/* Interlocked hexes overlap; the card being used comes to the top. */
.principle-cards .pc-card:hover,
.principle-cards .pc-card:focus-visible {
  z-index: 5;
}

/* The hexagonal front: art full-bleed behind, label overlaid. The clip
 * rides .pc-hexshape, an inner wrapper, so the drop-shadow filter and the
 * Rough.js border overlay on .pc-front can't be cut off by it — filter
 * applies after clip-path on the same element, which would clip the
 * shadow. */
.principle-cards .pc-front {
  grid-area: 1 / 1;
  position: relative;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
  min-width: 0;
  -webkit-transition: -webkit-transform 0.2s ease, -webkit-filter 0.2s ease;
  transition: -webkit-transform 0.2s ease, -webkit-filter 0.2s ease;
  transition: transform 0.2s ease, filter 0.2s ease;
  transition: transform 0.2s ease, filter 0.2s ease, -webkit-transform 0.2s ease, -webkit-filter 0.2s ease;
  -webkit-filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.14));
          filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.14));
}

.principle-cards .pc-hexshape {
  position: relative;
  -webkit-box-flex: 1;
      -ms-flex: 1;
          flex: 1;
  min-width: 0;
  -webkit-clip-path: var(--pc-hex);
          clip-path: var(--pc-hex);
  background: #fbf9f5;
  color: var(--pc-gold);
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: end;
      -ms-flex-pack: end;
          justify-content: flex-end;
  padding: 0 15% 14%;
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
}

.principle-cards .pc-card:hover .pc-front {
  -webkit-transform: translateY(-4px);
          transform: translateY(-4px);
  -webkit-filter: drop-shadow(0 8px 14px rgba(0, 0, 0, 0.18));
          filter: drop-shadow(0 8px 14px rgba(0, 0, 0, 0.18));
}

/* The Rough.js hand-drawn hexagon border (injected by the band's script when
 * data-rough-hex="on"). It rides the front OUTSIDE .pc-hexshape so the clip
 * can't cut the wobble off; currentColor keeps the stroke on the CSS palette;
 * non-scaling-stroke holds the drawn line at 1px however the card scales. */
.principle-cards .pc-rough {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  color: var(--pc-gold);
}

.principle-cards .pc-rough path {
  vector-effect: non-scaling-stroke;
}

/* Soft paper wash behind the title block so the label stays legible where
 * the board's ribbons run under it. Proportional like everything else: the
 * insets used to be four px values with two more sets in media queries, and
 * a wash sized for a 300px card swallowed a 150px one whole. */
.principle-cards .pc-title::before {
  content: "";
  position: absolute;
  top: calc(var(--pc-w) * -0.06);
  right: calc(var(--pc-w) * -0.085);
  bottom: calc(var(--pc-w) * -0.046);
  left: calc(var(--pc-w) * -0.085);
  background: radial-gradient(ellipse at center, rgba(251, 249, 245, 0.92) 55%, rgba(251, 249, 245, 0) 100%);
  z-index: -1;
}

.principle-cards .pc-front .pc-art-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* The hexshape stacks bottom-up (justify-content: flex-end), so this margin
 * is what holds the title block off the hexagon's lower point. It grew when
 * cb dropped the "Flip" caption on 2026-09-15: the block lost a line, and a
 * bottom-anchored block that loses its last line drops by exactly that much.
 * The extra half of gap-plus-caption keeps the block's CENTRE where it was,
 * which is the thing the eye was reading, rather than its top.
 *
 * --pc-label-foot is that value made proportional (0.09 of the card, which
 * is the 1.36rem it was on the 240px card it was measured on). It was a rem
 * on a card whose width is not — so the same deck at half the size kept a
 * full-size foot and pushed the label up into the icon. */
.principle-cards .pc-title {
  position: relative;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  text-align: center;
  margin-bottom: var(--pc-label-foot);
}

/* ── The label ───────────────────────────────────────────────────────────
 * One rule instead of five, sized off the card and bucketed on the LONGEST
 * WORD — the tile deck's rule, thresholds and all; tile_card.html carries
 * the measurement that set them (re-measured 2026-09-17, both bands at once,
 * when the map stopped shouting its labels in capitals).
 *
 * The longest word, not the string: what fails inside a hexagon is the
 * wrap, and a long word is the one thing that cannot be broken to fit. Two
 * short words at 1.45rem sit happily on two lines where one twelve-letter
 * word at the same size runs out through the clip. */
.principle-cards .pc-label {
  font-weight: 800;
  font-size: calc(var(--pc-w) * 0.115);
  line-height: 1.1;
  color: var(--pc-ink);
  text-wrap: balance;
}

.principle-cards .pc-label.pc-long {
  font-size: calc(var(--pc-w) * 0.095);
}

.principle-cards .pc-label.pc-xlong {
  font-size: calc(var(--pc-w) * 0.08);
}

/* ── Lit: the deck's first step ──────────────────────────────────────────
 * Two steps on one control, as the tiles take them — the first activation
 * lights a hexagon, the second turns it over. This is what lets a reader
 * (or a presenter) point at a card without covering the deck with it.
 *
 * A wash and a heavier ring, never an inversion: inverting turns
 * currentColor to paper, which takes the Rough border white and the ink
 * label with it. The board's ribbons come up with the face so the tint
 * reads as one object rather than as a card with a stain on it.
 *
 * ⚠️ The @supports guard is load-bearing, not politeness. An unsupported
 * color-mix STORED IN A CUSTOM PROPERTY fails at use time and falls back to
 * `inherit` — black ribbons — not to the sprite's own stroke attribute. The
 * ring alone is the signal where it is unsupported. */
.principle-cards .pc-lit .pc-front {
  -webkit-filter: drop-shadow(0 0 3px var(--pc-gold)) drop-shadow(0 0 3px var(--pc-gold))
    drop-shadow(0 0 4px var(--pc-gold));
          filter: drop-shadow(0 0 3px var(--pc-gold)) drop-shadow(0 0 3px var(--pc-gold))
    drop-shadow(0 0 4px var(--pc-gold));
  z-index: 4;
}

@supports (color: color-mix(in srgb, red 50%, blue)) {
  .principle-cards .pc-lit .pc-hexshape {
    background: color-mix(in srgb, var(--pc-gold) 16%, #fbf9f5);
  }

  .principle-cards .pc-lit {
    --pc-tile: color-mix(in srgb, var(--pc-gold) 40%, #fbf9f5);
  }
}

/* ── The hub ─────────────────────────────────────────────────────────────
 * A family names itself on a hexagon, which is what retired the colour
 * legend the slide used to carry: the reader no longer has to hold a key in
 * mind and carry it back to the deck.
 *
 * The face stays PAPER. The filled accent face the tile hubs wear is not
 * available here — --pc-gold is measured at >=3.2:1 on white, the graphical
 * threshold, because on a card it is a line, so words on it would fail
 * 1.4.3 (the tile deck hit exactly this and patched it with `hub_text:
 * ink`). --pc-gold-deep is already >=4.6:1 on paper. So what marks the hub
 * out is weight: the title in the deeper colour, and a Rough border drawn
 * twice — a heavier pen, not a different object.
 *
 * No icon, so the title takes the whole interior, centred. It does carry a
 * BOARD — one Tsuro cell, like a card (bands/principle_hub.html) — because
 * a hub sits among the cards that touch it, and a blank one would cut every
 * ribbon that runs into it. The map's hubs learned this first (the paths
 * run through the hub, societie-tiles.css). As there: the same width, no
 * casing, and lighter — the family's pale tile tint, which on the tinted
 * face is a quiet line and sits LIGHTER than the title, so the title's
 * contrast (measured on the face) can only rise over a ribbon. No wash. */
.principle-cards .pc-hub-art {
  --pt-casing: 0;
  pointer-events: none;
}

.principle-cards .pc-hub {
  display: grid;
  position: relative;
}

.principle-cards .pc-hub::before {
  content: "";
  grid-area: 1 / 1;
  padding-top: 115.473%;
}

.principle-cards .pc-hub-shape {
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  padding: 0 17%;
}

.principle-cards .pc-hub .pc-title {
  margin-bottom: 0;
}

.principle-cards .pc-hub .pc-title::before {
  content: none;
}

.principle-cards .pc-hub-label {
  color: var(--pc-gold-deep);
  font-weight: 700;
  /* A family title is a four- or five-word phrase where a card's label is
   * one or two, so it starts a step below the card's scale and the buckets
   * step down from there. */
  font-size: calc(var(--pc-w) * 0.095);
  line-height: 1.15;
}

.principle-cards .pc-hub-label.pc-long {
  font-size: calc(var(--pc-w) * 0.085);
}

.principle-cards .pc-hub-label.pc-xlong {
  font-size: calc(var(--pc-w) * 0.075);
}

/* THE HIGHLIGHT TINT. cb, 2026-09-17: "Each hub should take the highlight
 * tint, just like the other map." So every hub wears, permanently, the wash a
 * LIT card wears for a moment — the family's own colour at 16% on the paper —
 * and the family is marked by colour as the map's hubs are, not by weight
 * alone. It is the wash and not the map's solid fill for the reason above:
 * --pc-gold is a graphical-contrast colour.
 *
 * ⚠️ THE TINT COSTS THE TITLE ITS CONTRAST. --pc-gold-deep is measured on
 * white and falls to 3.8-4.0:1 on the tinted face (institution excepted), so
 * the title is taken a quarter of the way to --pc-ink on the same condition
 * that lays the tint: 5.4:1 at worst (work), 7.2:1 at best (institution).
 * Where color-mix is unsupported neither happens and the hub is the paper
 * hexagon it was, with the title at its paper contrast. Re-measure both if
 * a family colour changes (test_learning_principles.py does). */
@supports (color: color-mix(in srgb, red 50%, blue)) {
  .principle-cards .pc-hub .pc-hexshape {
    background: color-mix(in srgb, var(--pc-gold) 16%, #fbf9f5);
  }

  .principle-cards .pc-hub .pc-hub-label {
    color: color-mix(in srgb, var(--pc-gold-deep) 75%, var(--pc-ink));
  }
}

/* A family panel is a paragraph and a list of claims, not a card's back: it
 * has no icon, so its claim needs no margin clearing a chip. */
.principle-cards .pc-family-dialog .pc-claim {
  margin-right: 0;
}


/* ── The flip side: a lightbox dialog per card ──────────────────────────
 * The <dialog> itself is a transparent, padding-less box so a click that
 * lands on the ::backdrop (reported as the dialog element) closes it;
 * .pc-dialog-card is the visible card — black-with-accent, the site's own
 * btn-color($black, $gold) idiom, framed in the family colour. */
.principle-cards .pc-dialog {
  border: 0;
  padding: 0;
  background: transparent;
  width: 92vw;
  max-width: 34rem;
  max-height: 88vh;
}

/* A browser without <dialog> (Safari <15.4, Firefox <98) has no UA style
 * for it, so all 18 flip sides would render inline under the deck. Hide
 * closed dialogs explicitly (the UA sheet does the same where it exists). */
.principle-cards .pc-dialog:not([open]) {
  display: none;
}

/* Fallback modal, for that same browser: the band's script adds
 * .pc-no-dialog to the deck when showModal() is missing and then opens
 * cards by setting the open attribute itself, with a .pc-backdrop div
 * in place of ::backdrop. Scoped on the class so a native modal keeps
 * the UA's top-layer centring untouched. */
.principle-cards.pc-no-dialog .pc-dialog[open] {
  display: block;
  position: fixed;
  z-index: 10001;
  top: 50%;
  left: 50%;
  margin: 0;
  -webkit-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}

.principle-cards .pc-backdrop {
  position: fixed;
  z-index: 10000;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgba(12, 12, 12, 0.55);
}

.principle-cards .pc-dialog::-webkit-backdrop {
  /* ::backdrop doesn't inherit custom properties — literal colour only. */
  background: rgba(12, 12, 12, 0.55);
}

.principle-cards .pc-dialog::backdrop {
  /* ::backdrop doesn't inherit custom properties — literal colour only. */
  background: rgba(12, 12, 12, 0.55);
}

.principle-cards .pc-dialog-card {
  position: relative;
  background: #141414;
  color: #d9d4ca;
  border-radius: 8px;
  border-top: 6px solid var(--pc-gold);
  padding: 28px 32px 24px;
  -webkit-box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
          box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
  max-height: 82vh;
  overflow-y: auto;
  scrollbar-width: thin;
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
}

.principle-cards .pc-close {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: 0;
  -webkit-box-shadow: none;
          box-shadow: none;
  padding: 6px 10px;
  font-size: 1.5rem;
  line-height: 1;
  color: #d9d4ca;
  cursor: pointer;
}

.principle-cards .pc-close:focus-visible {
  outline: 3px solid var(--pc-back-accent, var(--pc-gold));
  outline-offset: 2px;
}

/* The card's family, worn as an eyebrow over the claim (it came off the
 * hexagon fronts when the lightbox arrived — cb, 2026-09-03). */
.principle-cards .pc-eyebrow {
  display: block;
  font-family: "Roboto Mono", monospace;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pc-back-accent, var(--pc-gold));
  margin: 0 88px 12px 0; /* right margin clears the icon chip */
}

/* The icon chip: the front's art SVG re-included, board and halo hidden,
 * cropped to the icon's fixed region of the 346.4x400 viewBox. The icon
 * group sits at translate(108.4,87.2) scale(5.4) — a 129.6-unit box — so
 * for a 56px chip the SVG renders at 56/129.6 of natural size and shifts
 * up-left by the group's offset at that scale. The stroke-width bump keeps
 * the line readable on black at chip size (CSS beats the presentation
 * attribute). */
.principle-cards .pc-dialog-icon {
  position: absolute;
  top: 30px;
  right: 26px;
  width: 56px;
  height: 56px;
  overflow: hidden;
  color: var(--pc-back-accent, var(--pc-gold));
}

.principle-cards .pc-dialog-icon svg {
  display: block;
  width: 149.7px;
  height: 172.8px;
  margin: -37.7px 0 0 -46.8px;
}

.principle-cards .pc-dialog-icon use,
.principle-cards .pc-dialog-icon circle {
  display: none;
}

.principle-cards .pc-dialog-icon g {
  stroke-width: 0.85;
}

.principle-cards .pc-claim {
  display: block;
  font-weight: 600;
  font-size: 1.35rem;
  line-height: 1.3;
  color: var(--pc-back-accent, var(--pc-gold));
  margin: 0 88px 18px 0; /* right margin clears the icon chip */
  text-wrap: balance;
}

/* The site styles definition lists globally (custom-styles.scss italicises
 * <dd>; content.scss lays <dl> out as a two-column grid with a ":" appended
 * to <dt> in .main-content scopes), so the dialog re-asserts the plain
 * stacked form explicitly rather than inheriting whatever the page scope is. */
.principle-cards .pc-dialog-card dl {
  display: block;
  margin: 0;
  font-size: 1.02rem;
  line-height: 1.6;
  letter-spacing: normal;
}

.principle-cards .pc-dialog-card dt::after {
  content: none;
}

.principle-cards .pc-dialog-card dt {
  text-align: left;
  font-family: "Roboto Mono", monospace;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pc-back-accent, var(--pc-gold));
  border-top: 1px solid #35322c;
  padding-top: 14px;
  margin-bottom: 8px;
}

.principle-cards .pc-dialog-card dd {
  margin: 0 0 18px;
  font-weight: 300;
  font-style: normal;
  letter-spacing: normal;
  white-space: normal;
}

/* The "By design" list — concrete course features that operationalise the
 * claim (the Design Elements column of AATD_Claims_v2.docx). Re-asserted
 * plain against the site's global list styling. */
.principle-cards .pc-design ul {
  margin: 0;
  padding-left: 1.15em;
  list-style: disc;
}

.principle-cards .pc-design li {
  margin: 0 0 7px;
  padding: 0;
}

/* ── Family colour bands ─────────────────────────────────────────────────
 * One colour per family, picked at sweet spots of the house hero span
 * (pipeline placeholder_art.py: sand-gold 40.7deg ... blue 213.1deg, no
 * red, no purple) and skipping the muddy olive stretch a smooth scale
 * has to cross: gold / emerald / teal / blue. Families sit in that order
 * in the YAML, so the deck still sweeps gold->green->blue in four bands.
 * Keyed on data-family — stamped by the band include on each card AND on
 * its dialog, so the lightbox wears its card's colour — not position, so
 * reordering the deck can't scramble a family's colour.
 *
 * Four contrast-clamped roles per family (family_colours.py, scratchpad,
 * session c3cbad03):
 *   --pc-gold        front accent: icon, Rough border, hexshape colour,
 *                    focus ring, dialog frame (>=3.2:1 on white)
 *   --pc-gold-deep   small mono hint text (>=4.6:1 on the paper)
 *   --pc-back-accent eyebrow, claim + dt on the black dialog card
 *                    (>=4.6:1 on #141414 — the front accents would fail
 *                    there; falls back to --pc-gold)
 *   --pc-tile        the board's tile-line tint (consumed inside
 *                    _tiles.svg as var(--pc-tile); casing stays white)
 */
.principle-cards [data-family="regard"] { --pc-gold: #be850e; --pc-gold-deep: #95690b; --pc-back-accent: #efaf2a; --pc-tile: #f3e9d3; }
.principle-cards [data-family="work"] { --pc-gold: #2d8659; --pc-gold-deep: #2b8055; --pc-back-accent: #53c68c; --pc-tile: #d3f3e3; }
.principle-cards [data-family="together"] { --pc-gold: #2b8388; --pc-gold-deep: #287c80; --pc-back-accent: #51c2c8; --pc-tile: #d3f1f3; }
.principle-cards [data-family="institution"] { --pc-gold: #235695; --pc-gold-deep: #235695; --pc-back-accent: #4585d3; --pc-tile: #d3e1f3; }

/* ── Narrow: one cluster across ──────────────────────────────────────────
 * The clusters wrap on their own — nothing here re-lays them out. All a
 * breakpoint has to do now is name a smaller card, and every proportion
 * follows it: the seats, the label, its foot, the paper wash behind it.
 * That is the whole of what three media blocks and two nth-child cycles
 * used to do.
 *
 * One cluster is 3w + 2gap across, so a 350px phone column wants a card
 * near 110px and a 300px one near 96.
 *
 * These blocks must sit BELOW the base rules they override: the selectors
 * tie on specificity, so source order is the only thing that lets them win.
 * ⚠️ None of them may ever apply to a SLIDE — see the slide block at the
 * foot of this file for why a media query cannot be trusted inside a deck. */
/* ⚠️ THE LAPTOP GAP, and it is arithmetic rather than taste. Two clusters
 * across need 2(3w + 2gap) + lap = 6.4w + 64 at the base sizes — 1011px,
 * against the 1074 the content column has once .container hits its 1106
 * max-width. It fits there and nowhere below it: at a 1024-wide laptop the
 * column is about 928, the second cluster wraps, and the comb goes from
 * roughly 950px tall to 1900. Nobody had seen that until 2026-09-16, when
 * /societie/introduction/ became a page and gave the band its first
 * non-slide host since the clusters replaced the nth-child comb.
 *
 * 128px is the largest card that fits two across in a 883px column, which is
 * a 980-wide window; below that one cluster per row is the honest answer and
 * the block below takes over at the phone sizes. The upper bound is where
 * the base 148 starts fitting on its own. */
/* ⚠️ NO WIDTH LADDER. --pc-w used to step 148 / 128 / 112 / 96 across four
 * media queries, and a phone block pulled the clusters out into the page
 * gutter, because a wrapping flex row had to be stopped from towering at
 * every width somebody eventually opened it at. The camera replaced all of
 * it on 2026-09-17: the field is one fixed shape and the camera fits it to
 * the box. A new --pc-w media query would zoom the field for no reason and
 * bring the drift back; size the VIEWPORT (--pc-map-h) instead.
 *
 * What is left here is the lightbox, which is real page layout and has no
 * camera. */
@media (max-width: 419px) {
  .principle-cards .pc-dialog-card { padding: 18px 18px 14px; }
  .principle-cards .pc-dialog-card dl { font-size: 0.92rem; }
  .principle-cards .pc-claim { font-size: 1.15rem; }
}

@media (prefers-reduced-motion: reduce) {
  .principle-cards .pc-front,
  .principle-cards .pc-card:hover .pc-front {
    -webkit-transition: none;
    transition: none;
    -webkit-transform: none;
            transform: none;
  }
}

/* ── The flip side, docked: the page's side third ────────────────────────
 * cb, 2026-09-17: "let's also throw the overlay to the side third - I liked
 * that gradient". The gradient is the slide's, and this is the same panel
 * the slide builds in mccusker-reveal.scss under .principle-comb — the band
 * now docks on a PAGE too (see dockTarget() in bands/principle_cards.html),
 * so the rules have to exist in both places.
 *
 * ⚠️ WHY THIS IS NOT ONE SHARED BLOCK. The slide's copy lives inside
 * `.reveal .slides > section.principle-comb`, which outranks anything here
 * by two classes and an element, so a slide never sees these rules — and
 * must not, because it restates every SIZE a third larger for a projector.
 * What is shared is the SHAPE (a full-height panel, a stripped card, paper
 * type, the ringed disc) and the WASH, and the wash is the part that would
 * actually be a defect if it drifted: two gradients that are nearly the same
 * read as a mistake. test_the_page_and_the_slide_wash_with_the_same_paper
 * pins these stops against $st-column-stops character for character.
 *
 * On a page the type is already set for a desk, so nothing here names a
 * font-size. The colours still have to change: the flip side's palette is
 * built for a black card (--pc-back-accent is measured on #141414) and this
 * is paper.
 *
 * Below DOCK_MIN (640px of field) the band does not dock at all and the
 * modal is what opens — a 20rem panel beside a 12rem field is not a
 * reading column, it is two slivers. There is no media query here because
 * the decision is about the FIELD's width, which a media query cannot see;
 * the band measures pcViewport.offsetWidth and simply doesn't add the
 * class. */
.principle-cards .pc-dialog.pc-docked {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: auto;
  /* The third cb asked for. The floor is the measure, not the layout: under
   * about 18rem the assumption/example definitions break to two or three
   * words a line and the panel is a column of fragments. At the 640px where
   * docking starts, the floor is what applies. */
  width: 34%;
  min-width: 18rem;
  /* The band's modal is a 34rem box centred in the window; all three of
   * those go, and so does the 88vh cap — this is measured on the viewport,
   * not on the window. */
  max-width: none;
  max-height: none;
  /* ⚠️ The UA sheet gives <dialog> `height: fit-content`, which is NOT
   * `auto` and so beats a top/bottom pair: the box would size to the words
   * and take the wash with it, painting a short panel down a tall field. */
  height: auto;
  margin: 0;
  padding: 0;
  border: 0;
  z-index: 4;
  /* Centre a short back in the panel; a tall one fills the height and
   * scrolls inside .pc-dialog-card. */
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  /* `cursor` inherits, and the viewport's is `grab` — without this the
   * reading panel offers to be dragged. */
  cursor: auto;
  /* THE WASH IS ON THE DIALOG, not on the card inside it, so the panel is
   * the full height of the field with the words centred in it. Put it on the
   * card and the flip side is a floating slab again, which is the thing it
   * has just stopped being.
   *
   * These four stops are $st-column-stops in mccusker-reveal.scss. An
   * rgba() triple is the documented exception to "never write a hex" — a
   * custom property cannot go inside rgba(). */
  background: -webkit-gradient(
    linear,
    left top, right top,
    from(rgba(251, 249, 245, 0.96)),
    color-stop(88%, rgba(251, 249, 245, 0.96)),
    to(rgba(251, 249, 245, 0))
  );
  background: linear-gradient(
    to right,
    rgba(251, 249, 245, 0.96) 0%,
    rgba(251, 249, 245, 0.96) 88%,
    rgba(251, 249, 245, 0) 100%
  );
}

.principle-cards .pc-dialog.pc-docked.pc-dock-right {
  left: auto;
  right: 0;
  background: -webkit-gradient(
    linear,
    right top, left top,
    from(rgba(251, 249, 245, 0.96)),
    color-stop(88%, rgba(251, 249, 245, 0.96)),
    to(rgba(251, 249, 245, 0))
  );
  background: linear-gradient(
    to left,
    rgba(251, 249, 245, 0.96) 0%,
    rgba(251, 249, 245, 0.96) 88%,
    rgba(251, 249, 245, 0) 100%
  );
}

/* ⚠️ .pc-viewport carries `touch-action: none` so the camera owns every
 * finger on the field, and a CHILD CANNOT TAKE THAT BACK — the browser
 * intersects touch-action down the ancestor chain, so `touch-action: auto`
 * on the panel would do nothing and a docked back would be unscrollable on
 * a tablet. The band adds .pc-panelled to the viewport while a panel is
 * open and removes it on close; panning a field you are not looking at is
 * the lesser loss. */
.principle-cards .pc-viewport.pc-panelled {
  -ms-touch-action: auto;
      touch-action: auto;
}

.principle-cards .pc-dialog.pc-docked .pc-dialog-card {
  width: 100%;
  max-height: 100%;
  overflow-y: auto;
  /* Everything that made this an OBJECT comes off — the black fill, the
   * radius, the accent rail across the top, the drop shadow. The wash above
   * is the panel; this is only the words in it. A card with a shadow inside
   * a wash that deliberately has no edge is two panels, and the reader can
   * see the seam. */
  background: none;
  border: 0;
  border-radius: 0;
  -webkit-box-shadow: none;
          box-shadow: none;
  /* The close button stays anchored to the WORDS, not to the panel: the
   * panel is full-height and the words are centred in it, so a button in the
   * panel's corner floats free of the block it belongs to. */
  position: relative;
  /* Asymmetric on purpose: wider on the side the fade is, so no line ends in
   * the gradient with a hexagon showing through the last two words. The wash
   * holds full strength to 88%, so the gutter has to be at least the last
   * 12% of the panel. */
  padding: 1.25rem 3rem 1.25rem 1.5rem;
}

.principle-cards .pc-dialog.pc-docked.pc-dock-right .pc-dialog-card {
  padding: 1.25rem 1.5rem 1.25rem 3rem;
}

/* ── The type, on paper ─────────────────────────────────────────────────
 * --pc-back-accent is measured against #141414 and must not appear here at
 * all. Nor can everything take --pc-gold: that is measured at >= 3.2:1, the
 * GRAPHICAL threshold, because on a card face it is a line and not words.
 * So --pc-gold keeps only the bullet marks and the claim (large text), and
 * every piece of small text goes to --pc-gold-deep (>= 4.6:1 on paper, same
 * hue) or to ink. */
.principle-cards .pc-dialog.pc-docked .pc-eyebrow {
  color: var(--pc-gold-deep);
  /* The right margin existed to clear the icon chip, which is hidden
   * below; the close disc shares this line instead, on the opaque side. */
  margin-right: 0;
  padding-left: 2.5rem;
}

.principle-cards .pc-dialog.pc-docked.pc-dock-right .pc-eyebrow {
  padding-left: 0;
  padding-right: 2.5rem;
}

.principle-cards .pc-dialog.pc-docked .pc-claim {
  color: var(--pc-gold);
  margin-right: 0;
}

.principle-cards .pc-dialog.pc-docked .pc-dialog-card dt {
  color: var(--pc-gold-deep);
  /* The rule under a section was a step UP from the black card; on paper it
   * has to come the other way down. */
  border-top: 1px solid var(--colour-rule);
}

.principle-cards .pc-dialog.pc-docked .pc-dialog-card dd {
  color: var(--pc-ink);
}

.principle-cards .pc-dialog.pc-docked .pc-design li::marker {
  color: var(--pc-gold);
}

/* The close button becomes a ringed disc on the eyebrow's own line, at the
 * OPAQUE edge of the panel: at the fade it would be half over the field. */
.principle-cards .pc-dialog.pc-docked .pc-close {
  top: 0.9rem;
  left: 1.5rem;
  right: auto;
  padding: 0;
  color: var(--pc-ink);
  border: 1px solid currentColor;
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  line-height: 1;
  font-size: 1.25rem;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  opacity: 0.55;
}

.principle-cards .pc-dialog.pc-docked.pc-dock-right .pc-close {
  left: auto;
  right: 1.5rem;
}

.principle-cards .pc-dialog.pc-docked .pc-close:hover,
.principle-cards .pc-dialog.pc-docked .pc-close:focus-visible {
  opacity: 1;
}

/* The base ring is the family accent, for a paper x on a black card. On
 * paper that accent is a 3:1 line colour under a 2rem disc — ink. */
.principle-cards .pc-dialog.pc-docked .pc-close:focus-visible {
  outline-color: var(--pc-ink);
}

/* The icon chip goes. It is the CARD'S OWN MARK and the card it belongs to
 * is lit on the same field, a few hundred pixels away — the same drawing
 * twice. In the modal it earns its place because there is no field behind
 * it. It also could not stay where it was: pinned to the card's right edge
 * it lands on the 88% stop, the first pixel of the fade. */
.principle-cards .pc-dialog.pc-docked .pc-dialog-icon {
  display: none;
}


/* ── slide variant (`slide=true`) ─────────────────────────────────────────
 * The deck on a reveal.js slide — /societie/introduction/, second slide.
 * cb, 2026-09-15: "Can we add in the Principles in the honeycomb pattern?",
 * and then, of the two ways to do it, "its own honeycomb slide".
 *
 * ⚠️ WHY A MEDIA QUERY CANNOT DO THIS, however obviously it looks as though
 * it could. A media query inside a deck is evaluated against the REAL
 * VIEWPORT, not against reveal's 1920x1080 canvas. The canvas is then scaled
 * to fit, so the slide is 1920 wide in the only coordinate system its layout
 * lives in while the viewport deciding the query might be 1000 — and the
 * slide silently takes the phone's numbers on the very laptop it is being
 * presented from. That is measured, not feared: it used to move the labels
 * between 1.45rem and 1.02rem on cards that were 178px either way.
 *
 * So: NO RULE FOR A SLIDE MAY SIT INSIDE A MEDIA QUERY, and the sizes here
 * must OUTRANK the narrow-screen blocks above, which set the same custom
 * properties on `.principle-cards` — (0,1,0) there against (0,2,0) here, so
 * this wins wherever it sits in the file.
 *
 * That is now the whole of the slide's CSS, and the reason is the point of
 * the 2026-09-16 rebuild: the deck is a proportion of one width, so naming
 * the width is naming the layout. This block used to also pin the label
 * size, the paper wash and the row geometry, one rule each, because each of
 * those was an absolute value that some media query would otherwise move. */
.principle-cards.pc-slide {
  /* ⚠️ Since the camera arrived (2026-09-17) these numbers no longer decide
   * how big a card LOOKS — the field is scaled to fit the viewport, so
   * --pc-w is a RESOLUTION and changing it zooms. What they still decide is
   * the ratio of card to air: the gap is 12/140 of the card here against
   * 0.115 on the page, which is a slightly tighter weave for a projector.
   *
   * They used to be load-bearing in a second way — four cluster BOXES had to
   * fit 1820px of a 1920 canvas, and --pc-cluster-lap was the slack that
   * bought it. There are no cluster boxes any more (see THE FIELD in
   * bands/principle_cards.html): the field is sized to the bounds of what is
   * placed, so there is nothing left to overflow and the lap is gone. */
  --pc-w: 140px;
  --pc-gap: 12px;
}
