/* [LarenX]: Board layout | games/Master-Mind/css/board.css | v.1.0
 *
 * The page of a comic album, not a game screen. One tier of panels per row, the
 * panel being played opened out to full width because that is the panel the page
 * is built around, and every panel still to come left in blue pencil.
 */

/* The window is the magazine and nothing else. The page is already sized to the
 * window rather than to its contents, so there is never anything below the fold;
 * locking the scroll keeps the browser from drawing a bar over the sheet anyway,
 * which on a comic page reads as a printing fault. The tribute page is a long
 * read and is not styled by this file, so it keeps its scroll. */
html, body {
  height: 100%;
  overflow: hidden;
}

.magazine {
  height: 100vh;
  box-sizing: border-box;
  overflow: hidden;
  padding: clamp(10px, 2.5vw, 34px);
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

/* The same sheet as the cover, because it is the same magazine. A4, sized to the
 * window rather than to its contents, so the page never grows a scrollbar: a
 * comic page you have to scroll is not a page, it is a list.
 *
 * Everything inside therefore has to fit, which is what forces the panels to
 * shrink on the long levels instead of running off the bottom. --cell is
 * measured and written by the script once the sheet has a height. */
.page {
  /* Nothing is printed off the edge of the paper. The panels are free to break
   * out of their own borders, which is the one thing Polch did that this game
   * copies outright; they are not free to break out of the sheet. */
  overflow: hidden;
  padding: clamp(10px, 1.8vh, 24px);
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 1vh, 14px);
}

/* ------------------------------------------------------------ issue head --- */

/* The masthead strip a magazine episode opened with: the title of the magazine,
 * the episode number, and the story's own title under a heavy rule. */
.head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  border-bottom: var(--rule) solid var(--ink);
  padding-bottom: 6px;
}

.head__magazine {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.6vw, 1.7rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.head__episode {
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.head__title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4.4vw, 2.6rem);
  width: 100%;
  margin: 2px 0 0;
}

.head__meta {
  display: flex;
  gap: 16px;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* The opening caption. Every page in the references starts with a small ruled
 * box like this, sitting over the top left of the first panel: "O swicie." It
 * carries the episode and the state of the watch, and it replaces the magazine
 * masthead that used to sit here, which belongs on the cover and nowhere else. */


/* The sheet carries the pause plate, which is laid over it. Its position comes
 * from .sheet-of-paper in print.css and must not be set again here: a relative
 * declared after the absolute one wins on the cascade, and the page then takes
 * its top and left as an offset instead of as a place. That is how it ended up
 * half off the table and cut at the foot. */


.magazine {
  flex-direction: column;
  align-items: center;
}

/* ----------------------------------------------------------------- strip --- */

/* --panel-min is written by the script from the peg count, so a three peg level
 * lays out two panels to a tier and a ten peg level takes the full width. The
 * grid decides; nothing is hardcoded per level. */
.strip {
  display: grid;
  /* Twelve columns that no panel matches, so panels take unequal bites and the
   * tiers come out uneven, which is how every page in the references is built.
   * A regular grid reads as a spreadsheet; this reads as a page. */
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: min-content;
  align-content: start;
  gap: clamp(4px, 0.75vh, 9px);
  flex: 1 1 auto;
  min-height: 0;
}

/* ----------------------------------------------------------------- panel --- */

.panel {
  position: relative;
  border: var(--rule) solid var(--ink);
  background: var(--paper-shade);
  padding: 6px 9px;
  min-height: var(--panel-h, 60px);
  display: flex;
  align-items: center;
  gap: 8px;
  /* The safety net. If the arithmetic in fit() is ever wrong again, the reply
   * drops under the marks instead of walking off the sheet. A wrapped panel is
   * ugly; an unreadable one is broken. */
  flex-wrap: wrap;
  overflow: visible;
}

.panel .seq { min-width: 0; }

.panel--blau {
  min-height: var(--panel-h, 60px);
  background: transparent;
  border-width: var(--rule-thin);
  border-style: solid;
}

/* The panel in play takes the tier to itself and sits heavier on the page. */
.panel--active {
  grid-column: 1 / -1;
  min-height: calc(var(--panel-h, 60px) * 1.7 + 8px);
  flex-direction: column;
  align-items: stretch;
  gap: 14px;
  padding: 30px 16px 16px;

  /* A flat tint with a dot screen over it, a shade darker than the sheet. This is
   * how a printed comic lifted one panel out of the page, and it marks the frame
   * the player is actually working in. */
  background-color: #e0d6ba;
  background-image:
    radial-gradient(circle at 50% 50%, rgba(33, 30, 26, 0.13) 30%, transparent 32%);
  background-size: 3px 3px;
  border-width: 3.4px;
  box-shadow: 5px 5px 0 rgba(33, 30, 26, 0.18);
}

.panel__scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* The number sits ON the corner of the panel, half in and half out, the way a
 * numbered tab is stuck to a plate. It used to sit inside, which cost the panel
 * a strip of height it could not spare and made the marks dodge round it.
 * Daniel: it may cover half a glyph, the glyphs are big enough now. */
.panel__index {
  position: absolute;
  top: -8px;
  left: -5px;
  background: #fffdf6;
  color: var(--ink);
  border: 1.6px solid var(--ink);
  box-shadow: 1.5px 1.5px 0 rgba(33, 30, 26, 0.55);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 1px 6px;
  z-index: 7;
}

.panel--blau .panel__scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* The signals stand in the scene, on the ground line, like figures in a shot.
 * The row being assembled is exempt: that panel is a desk, not a landscape. */
.panel .seq:not(.seq--active) {
  align-self: flex-end;
  margin-bottom: 5px;
  gap: 7px;
}

/* Unless the panel is too short for that, in which case standing them on the
 * ground line runs them under the number badge in the top left corner and the
 * badge covers a signal.
 *
 * The first fix centred them, which pushed the marks hard right in the proof
 * panels, where there is no reply to balance against. Indenting past the badge is
 * simpler, keeps them left aligned like every other panel, and is the thing the
 * problem actually asked for. The script decides when; see fillSheet. */
.page--short .panel .seq:not(.seq--active) {
  align-self: center;
  margin-bottom: 0;
}

/* A printed signal has NO box. Boxes were the whole reason the page read as
 * squares inside squares on squares: a bordered cell, inside a bordered panel,
 * inside a bordered sheet. The glyph carries its own paper coloured halo, which
 * is what lets it stand on painted colour and stay legible. */
.mark {
  width: calc(var(--cell, 30px) * 1.5);
  height: calc(var(--cell, 30px) * 1.5);
  flex: 0 0 auto;
  position: relative;
  filter: drop-shadow(1.5px 2px 0 rgba(33, 30, 26, 0.38));
}

/* A proof panel shows where the signals will stand, as empty pencil circles. */
.mark--blau {
  filter: none;
  border: var(--rule-thin) dashed var(--blau-pale);
  border-radius: 50%;
}

/* What the glasses show, in the alien's own register, which is the one colour on
 * the page that belongs to nothing else.
 *
 * A ring means the signal was in exactly this position. A slash means it was
 * not. Both are drawn, because only ringing the exact ones meant that looking at
 * a broadcast with no exact hits showed nothing whatsoever, and a charge spent
 * for a blank panel reads as a broken game rather than as an answer. */
.mark--seen::after {
  content: '';
  position: absolute;
  inset: -5px;
  border: 2.6px solid #2f9c94;
  border-radius: 50%;
}

.mark--miss::after {
  content: '';
  position: absolute;
  left: 50%;
  top: -7px;
  bottom: -7px;
  width: 3.4px;
  margin-left: -1.7px;
  background: #2f9c94;
  box-shadow: 0 0 0 1.4px #fffdf6;
  transform: rotate(34deg);
}

/* The page remembers which broadcast was looked at. */
.panel__seen {
  position: absolute;
  right: 6px;
  top: 4px;
  z-index: 6;
  background: #2f9c94;
  color: #fffdf6;
  font-size: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 1px 6px;
}

/* The splash: the panel a comic saves for the moment the story turns. Full width,
 * twice the height of a tier, the scene at its most extreme, and the line of the
 * message the player has just broken out of the transmission. */
.panel--splash {
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 8px;
  padding: 16px 20px 12px;
  min-height: calc(var(--panel-h, 60px) * 2.6 + 16px);
  border-width: 4px;
  box-shadow: 6px 6px 0 rgba(33, 30, 26, 0.3);
  overflow: hidden;
}

.splash__onom {
  position: absolute;
  right: 12px;
  top: 6px;
  z-index: 6;
  font-size: clamp(1.6rem, 4.4vw, 3.4rem);
}

.splash__head {
  align-self: flex-start;
  position: relative;
  z-index: 5;
}

/* The decoded line, lettered over the art the way a comic letters the line that
 * matters most on the page. */
.splash__line {
  position: relative;
  z-index: 5;
  margin: 2px 0 0;
  font-size: clamp(1rem, 2.9vw, 2rem);
  line-height: 1.05;
  color: #fffdf6;
  -webkit-text-stroke: clamp(1.6px, 0.4vw, 3px) var(--ink);
  paint-order: stroke fill;
  text-shadow: 3px 3px 0 rgba(33, 30, 26, 0.7);
  max-width: 92%;
}

.splash__all {
  position: relative;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: rgba(255, 253, 246, 0.9);
  border: var(--rule-thin) solid var(--ink);
  padding: 5px 9px;
  font-size: clamp(0.5rem, 1.05vh, 0.68rem);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  align-self: flex-start;
  max-width: 92%;
}

.splash__all b { letter-spacing: 0.14em; margin-bottom: 2px; }
.splash__all span { color: var(--ink-soft); }

/* Signing the log: a line on the splash, not a dialog over it. */
.sign {
  position: relative;
  z-index: 5;
  display: flex;
  gap: 7px;
  align-items: center;
  align-self: flex-start;
  flex-wrap: wrap;
}

.sign__name {
  font-family: var(--font-letter);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 7px 10px;
  border: var(--rule) solid var(--ink);
  background: #fffdf6;
  color: var(--ink);
  min-width: 15ch;
}

.sign__name:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

.sign--done {
  margin: 0;
  background: #fffdf6;
  border: var(--rule-thin) solid var(--ink);
  padding: 5px 10px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.panel--splash .console { position: relative; z-index: 5; border-top-color: rgba(33, 30, 26, 0.5); }

/* The panel that closes the episode. */
.panel--end {
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  padding: 28px 16px 14px;
  background: var(--paper);
  border-width: 3.4px;
  box-shadow: 5px 5px 0 rgba(33, 30, 26, 0.18);
  min-height: calc(var(--panel-h, 60px) * 1.7 + 8px);
}

.panel--end .panel__caption b { letter-spacing: 0.14em; }

.end__secret { justify-content: center; flex: 1 1 auto; }

/* --------------------------------------------------------- the desk panel --- */

/* The controls are the last panel of the page. They used to be a bar under the
 * sheet, which pushed the page around and looked like a website. */
.panel--desk {
  min-height: 0;
  padding: 7px 12px;
  justify-content: space-between;
  gap: 14px;
  background: #ded2b4;
  flex-wrap: wrap;
}

.desk__read {
  font-size: clamp(0.56rem, 1.1vh, 0.76rem);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.desk__read b { color: var(--ink); }

.desk__tools { display: flex; gap: 7px; flex-wrap: wrap; }

/* The episode caption sits inside the first panel, where the reference plates
 * put it, instead of floating over the page and landing on the next frame. */
.panel__slug {
  position: absolute;
  top: 4px;
  left: 42px;
  z-index: 6;
  font-size: clamp(0.5rem, 1.02vh, 0.68rem);
  max-width: calc(100% - 52px);
}

.panel--blau .panel__index {
  background: transparent;
  color: var(--blau);
  border: var(--rule-thin) solid var(--blau-pale);
}

/* The narration box in the panel being played is part of the flow, not floated
 * over it. Absolutely positioned it looked right on a one line caption and lay
 * straight across the signal slots the moment the text ran to two, which is most
 * of the time: the lines in the pool are sentences, not labels. */
.panel__caption {
  align-self: flex-start;
  margin-left: 36px;
  max-width: calc(100% - 44px);
  z-index: 4;
}

/* ------------------------------------------------------------- sequence --- */

.seq {
  display: flex;
  gap: 5px;
  flex: 0 1 auto;
  flex-wrap: nowrap;
  align-items: center;
}

.seq--active { gap: 8px; flex-wrap: wrap; }

.cell {
  width: var(--cell, 30px);
  height: var(--cell, 30px);
  flex: 0 0 auto;
  border: var(--rule-thin) solid var(--ink);
  background: var(--paper);
  padding: 4px;
  position: relative;
}

.seq--active {
  flex: 1 1 auto;
  justify-content: center;
  align-items: center;
}

.seq--active .cell {
  width: var(--cell-big, 46px);
  height: var(--cell-big, 46px);
  cursor: pointer;
}

.cell--empty { border-style: dashed; background: transparent; }

.cell--blau { border-color: var(--blau-pale); background: transparent; }

.cell--selected {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}

.cell:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}

/* The glasses mark a position that was exact, and only in the panel the player
 * chose to look at again. The ring is drawn in the alien's own register, which
 * is the one colour on the page that belongs to nothing else. */
.cell--seen::after {
  content: '';
  position: absolute;
  inset: -5px;
  border: 2.4px solid #3fb0a8;
  border-radius: 50%;
  pointer-events: none;
}

/* -------------------------------------------------------------- feedback --- */

.verdict {
  display: flex;
  gap: 3px;
  flex: 0 1 auto;
  min-width: 0;
  align-items: center;
  margin-left: auto;
  margin-right: 10px;
  padding: 0.38em 0.45em;
}

.verdict__box {
  min-width: 32px;
  padding: 0.2em 0.35em;
  text-align: center;
  line-height: 1.05;
}

.verdict__n {
  display: block;
  font-family: var(--font-display);
  font-size: 1.05rem;
}

.verdict__label {
  display: block;
  font-size: 0.5rem;
  letter-spacing: 0.1em;
}

/* The sound word stays inside its own frame. Hung below the border it looked
 * right on a single panel and was painted over by the next tier every time. */
.panel__onom {
  position: absolute;
  right: 8px;
  bottom: 4px;
  z-index: 5;
}

/* ------------------------------------------------------------- the desk --- */

.console {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  border-top: var(--rule-thin) dashed var(--ink-soft);
  padding-top: 12px;
}

.palette {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
}

.pick {
  width: calc(var(--cell-big, 46px) * 0.92);
  height: calc(var(--cell-big, 46px) * 0.92);
  padding: 5px;
  border: var(--rule-thin) solid var(--ink);
  background: var(--paper);
  cursor: pointer;
  position: relative;
  transition: transform 0.08s ease-out;
}

.pick:hover  { transform: translateY(-2px); }
.pick:active { transform: translateY(0); }

/* A signal in hand is lifted off the desk, not blacked out. Filling it with ink
 * hid the very glyph the player is choosing, and on a fresh board it made the
 * game look as though it had already chosen for them.
 *
 * The ring is a one shot: the class is applied fresh on every pick, so the pulse
 * replays each time a signal is taken up. */
.pick--armed {
  border-width: 2.6px;
  transform: translateY(-3px);
  box-shadow: 0 4px 0 rgba(33, 30, 26, 0.45);
  background: #fffdf6;
}

.pick--armed::after {
  content: '';
  position: absolute;
  inset: -3px;
  border: 2.4px solid #2f9c94;
  pointer-events: none;
  animation: mm-pulse 0.45s ease-out 1;
}

@keyframes mm-pulse {
  0%   { inset: -2px;  opacity: 1;    border-width: 3px; }
  100% { inset: -13px; opacity: 0;    border-width: 1px; }
}

@media (prefers-reduced-motion: reduce) {
  .pick--armed::after { animation: none; opacity: 0.8; inset: -3px; }
}

.pick:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .pick { transition: none; }
  .pick:hover { transform: none; }
}

/* --------------------------------------------------------------- buttons --- */

.btn {
  font-family: var(--font-letter);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 10px 18px;
  border: var(--rule) solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  box-shadow: 3px 3px 0 var(--ink);
}

.btn:hover  { background: var(--paper-shade); }
.btn:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }

.btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  box-shadow: none;
}

.btn--send { background: #d9a01e; }
.btn--send:hover { background: #e4ae2e; }

/* Signing the log is the one thing left to do on a won sheet, and it sits at the
 * foot of a page full of panels where it is easy to walk past. So it breathes: a
 * green lamp under the button, the light on a console that wants an answer, not a
 * web notification. Slow on purpose, and it stops the moment the run is signed,
 * because a lamp that never goes out is noise. */
.btn--sign {
  border-color: #1f6b46;
  color: #14532e;
  animation: mm-lamp 2.4s ease-in-out infinite;
}

@keyframes mm-lamp {
  0%, 100% { box-shadow: 0 0 0 0 rgba(63, 190, 120, 0); }
  50%      { box-shadow: 0 0 15px 4px rgba(63, 190, 120, 0.6); }
}

@media (prefers-reduced-motion: reduce) {
  .btn--sign { animation: none; box-shadow: 0 0 10px 3px rgba(63, 190, 120, 0.45); }
}

.btn--quiet {
  border-width: var(--rule-thin);
  box-shadow: none;
  font-size: 0.7rem;
  padding: 7px 12px;
}

.btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }

/* ---------------------------------------------------------------- foot --- */


.foot__tools { display: flex; gap: 8px; flex-wrap: wrap; }

.foot__credit {
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
  text-transform: uppercase;
  max-width: 44ch;
  line-height: 1.5;
}

.foot__credit a { color: inherit; }

/* --------------------------------------------------------------- mobile --- */

@media (max-width: 620px) {
  .page { width: 96vw; }
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* ----------------------------------------------------------- the reply --- */

/* The verdict is the alien answering, so it is drawn as a radio balloon: the
 * spiked outline comics have always used for a voice arriving through a speaker
 * rather than out of a mouth. Two stacked shapes, because clip-path throws away
 * a border: a black one behind, a paper one a little smaller in front.
 *
 * The reference pages Daniel supplied settled this. They are full of balloons
 * and caption boxes, and the game had neither: it had two rectangles of numbers.
 */
.verdict {
  position: relative;
  padding: 0.5em 0.7em;
  isolation: isolate;
  z-index: 4;
}

.verdict::before,
.verdict::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  -webkit-clip-path: polygon(0.0% 0.0%, 11.1% 7.0%, 22.2% 0.0%, 33.3% 7.0%, 44.4% 0.0%, 55.6% 7.0%, 66.7% 0.0%, 77.8% 7.0%, 88.9% 0.0%, 100.0% 0.0%, 93.0% 20.0%, 100.0% 40.0%, 93.0% 60.0%, 100.0% 80.0%, 100.0% 100.0%, 88.9% 93.0%, 77.8% 100.0%, 66.7% 93.0%, 55.6% 100.0%, 44.4% 93.0%, 33.3% 100.0%, 22.2% 93.0%, 11.1% 100.0%, 0.0% 100.0%, 7.0% 80.0%, 0.0% 60.0%, 7.0% 40.0%, 0.0% 20.0%);
          clip-path: polygon(0.0% 0.0%, 11.1% 7.0%, 22.2% 0.0%, 33.3% 7.0%, 44.4% 0.0%, 55.6% 7.0%, 66.7% 0.0%, 77.8% 7.0%, 88.9% 0.0%, 100.0% 0.0%, 93.0% 20.0%, 100.0% 40.0%, 93.0% 60.0%, 100.0% 80.0%, 100.0% 100.0%, 88.9% 93.0%, 77.8% 100.0%, 66.7% 93.0%, 55.6% 100.0%, 44.4% 93.0%, 33.3% 100.0%, 22.2% 93.0%, 11.1% 100.0%, 0.0% 100.0%, 7.0% 80.0%, 0.0% 60.0%, 7.0% 40.0%, 0.0% 20.0%);
}

.verdict::before { background: var(--ink); }

.verdict::after {
  inset: 2px;
  background: #fffdf6;
}

/* The tail, pointing back at the broadcast it is answering. */
.verdict__tail {
  position: absolute;
  left: -9px;
  top: 58%;
  width: 14px;
  height: 11px;
  background: var(--ink);
  -webkit-clip-path: polygon(100% 0%, 0% 52%, 100% 100%);
          clip-path: polygon(100% 0%, 0% 52%, 100% 100%);
}

.verdict__box { background: none; border: 0; }

/* --------------------------------------------------------- page number --- */

/* Every page in the references carries one, centred at the foot. */
.sheet__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px;
  margin: 0;
}

.sheet__small {
  margin: 0;
  font-size: 0.43rem;
  letter-spacing: 0.06em;
  line-height: 1.4;
  color: #9b9282;
  text-transform: uppercase;
  max-width: 62%;
}

.page__number {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  margin: 0;
}

/* ---------------------------------------------------------------- pause --- */

/* The watch can be held, and holding it covers the sheet. A pause that leaves the
 * broadcasts on the page is not a pause, it is unlimited thinking time with the
 * clock switched off, and the board would then rank whoever was not interrupted.
 * The blue is the proof sheet's own: what you are looking at is a page pulled off
 * the press half printed. */
.held {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(125, 157, 196, 0.985);
}

.held__plate {
  background: var(--paper);
  border: var(--rule) solid var(--ink);
  box-shadow: 7px 7px 0 var(--ink);
  padding: clamp(14px, 3.4vh, 32px) clamp(18px, 4vw, 46px);
  text-align: center;
  max-width: 80%;
}

.held__title {
  display: block;
  font-size: clamp(1.1rem, 4.2vh, 2.3rem);
  line-height: 1.05;
  letter-spacing: 0.05em;
}

.held__note {
  margin: 0.7em auto 0;
  max-width: 34ch;
  font-size: clamp(0.66rem, 1.6vh, 0.86rem);
  line-height: 1.5;
  color: var(--ink-soft);
}

.held__clock {
  margin: 0.5em 0 1.1em;
  font-family: var(--font-letter);
  font-size: clamp(0.66rem, 1.6vh, 0.86rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
