/*
  Tokens for the lull site.

  Four roots decided this file:
    what it is   a zero-dependency TypeScript library about conversation timing
    voice        declarative and technical; a line belongs here only if it could
                 sit in the README without changing register
    temperature  sober, near monochrome, with one moment of expression
    density      medium; one reading column, instruments run full width
*/

:root {
  /* Colour. Named for what the page is about, not for rank.
     Paper is cooled off deliberately: the warm cream that pairs with a serif
     display is the most common look in this genre, and the subject is a room
     going quiet, not a book. */
  --paper: #f1f3f2;
  --sheet: #fbfbfa;
  --ink: #14181b;
  --graphite: #5f686e;
  --rule: #d9ddd8;

  /* The one accent. It marks a single thing: the moment the system speaks.
     Indigo rather than an alert colour, because a turn firing is the expected
     outcome and not a warning.
     Measured contrast, sRGB relative luminance:
       --sheet on --speech   13.1:1   (inverted turn block)
       --speech on --paper    11.8:1   (links, focus ring) */
  --speech: #2a2470;

  /* Type. A monospace carries the display role because the subject is
     timestamps, event names and a deadline in milliseconds; the serif carries
     running prose so the two roles never blur. */
  --face-data: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;
  --face-prose: 'Source Serif 4', Georgia, 'Times New Roman', serif;

  /* Scale. Body 17px at a 68ch measure, stepped by 1.25. Rounded to whole
     pixels so hairlines and baselines stay crisp. */
  --size-body: 1.0625rem; /* 17px */
  --size-lead: 1.3125rem; /* 21px */
  --size-section: 1.6875rem; /* 27px */
  --size-title: 2.0625rem; /* 33px */

  /* Space. Base 8, then 1.5 steps. Two half steps exist because hairline
     labels sit closer to their value than paragraphs sit to each other. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;

  --measure: 68ch;
  --page: 1080px;

  /* Motion. Four steps, each tied to what it serves rather than picked per
     callsite. The longest belongs to the turn firing, which is the only event
     on the page that carries weight; nothing else is allowed to take as long.
     One easing, decelerating, because everything here is something arriving.
     The figure roll below sits outside that rule and says why. */
  --tempo-tap: 90ms;
  --tempo-quick: 160ms;
  --tempo: 260ms;
  --tempo-speak: 420ms;
  /* The benchmark figures are the exception, and they earn it by not being a
     response to anything: nobody is waiting on them, and 20,888 needs long
     enough to be watched arriving rather than glimpsed. Every duration that
     answers an action stays at or under --tempo-speak. */
  --tempo-figure: 1100ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Two things this sheet does not have, so their absence reads as a decision
   rather than an oversight. No corner is rounded: the page is a ruler, a strip
   and a log, and every one of those objects has square corners in the world it
   comes from. Nothing casts a shadow: separation is carried by hairlines, which
   is what a printed instrument would use. */

/* One theme, decided rather than omitted. The page has a single expressive
   device: an instrument that inverts from paper to ink at the instant a turn
   fires. On a dark ground that inversion has nowhere to go. Shipping a second
   palette that nobody opened would be worse than one that was chosen. */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--face-prose);
  font-size: var(--size-body);
  line-height: 1.62;
  font-synthesis-weight: none;
}

h1,
h2,
h3 {
  font-family: var(--face-data);
  font-weight: 500;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0;
}

p,
li {
  text-wrap: pretty;
}

a {
  color: var(--speech);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--speech);
  outline-offset: 3px;
}

code {
  font-family: var(--face-data);
  font-size: 0.9em;
}

.page {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 var(--space-5);
}

.column {
  max-width: var(--measure);
}

/* Masthead ---------------------------------------------------------------- */

.masthead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-5) 0;
  border-bottom: 1px solid var(--rule);
}

.wordmark {
  font-family: var(--face-data);
  font-size: var(--size-lead);
  font-weight: 500;
  letter-spacing: 0.08em;
}

.masthead nav {
  display: flex;
  gap: var(--space-5);
  font-family: var(--face-data);
  font-size: 0.875rem;
}

/* Hero -------------------------------------------------------------------- */

.hero {
  padding: var(--space-8) 0 var(--space-7);
}

/* The transcript is the page's opening argument, so it is set at reading size
   rather than as a caption, and each line keeps its own timestamp.

   It also arrives the way it was typed: one line after another, 80ms apart.
   That is the page's only load sequence, and it ends before the reader could
   have finished the first line. */
@keyframes arrive {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

.transcript li,
.thesis,
.standfirst {
  animation: arrive var(--tempo) var(--ease-out) both;
}

.transcript li:nth-child(2) {
  animation-delay: 80ms;
}

.transcript li:nth-child(3) {
  animation-delay: 160ms;
}

.transcript li:nth-child(4) {
  animation-delay: 240ms;
}

.thesis {
  animation-delay: 340ms;
}

.standfirst {
  animation-delay: 420ms;
}

.transcript {
  font-family: var(--face-data);
  font-size: var(--size-body);
  line-height: 2;
  margin: 0 0 var(--space-6);
  padding: 0;
  list-style: none;
  color: var(--graphite);
}

.transcript b {
  color: var(--ink);
  font-weight: 400;
}

.transcript time {
  display: inline-block;
  min-width: 9ch;
}

/* The hero line leaves the type scale. The scale is built for a 68ch reading
   column and this line is four words that have to carry the whole page. */
.thesis {
  font-family: var(--face-data);
  font-weight: 500;
  font-size: clamp(2.0625rem, 5.5vw, 3.75rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  margin: 0 0 var(--space-5);
  max-width: 22ch;
}

.standfirst {
  font-size: var(--size-lead);
  max-width: var(--measure);
  margin: 0;
  color: var(--graphite);
}

.standfirst strong {
  color: var(--ink);
  font-weight: 600;
}

/* Instrument -------------------------------------------------------------- */

.instrument {
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--space-6);
  margin: var(--space-7) 0 var(--space-9);
}

.instrument__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}

.label {
  font-family: var(--face-data);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--graphite);
}

.strip {
  position: relative;
  height: 132px;
  border: 1px solid var(--rule);
  background: var(--paper);
  overflow: hidden;
}

.strip__ruler {
  position: absolute;
  inset: auto 0 0 0;
  height: 22px;
  border-top: 1px solid var(--rule);
  font-family: var(--face-data);
  font-size: 0.6875rem;
  color: var(--graphite);
}

.strip__second {
  position: absolute;
  bottom: 0;
  transform: translateX(-50%);
  padding-top: 3px;
}

.strip__mark {
  position: absolute;
  bottom: 50px;
  width: 2px;
  height: 42px;
  background: var(--ink);
  transform: translateX(-1px);
}

.strip__mark--dropped {
  background: var(--rule);
  border-left: 1px dashed var(--graphite);
  width: 0;
}

/* The turn band is the inversion the whole palette exists for. It sits under
   the message marks rather than over them, so a reader can see both the
   balloons and the single turn they became. */
.strip__turn {
  position: absolute;
  bottom: 22px;
  height: 26px;
  background: var(--speech);
  color: var(--sheet);
  font-family: var(--face-data);
  font-size: 0.75rem;
  display: flex;
  align-items: center;
  padding: 0 var(--space-2);
  white-space: nowrap;
  overflow: hidden;
  animation: speak var(--tempo-speak) var(--ease-out);
}

@keyframes speak {
  from {
    transform: scaleY(0.4);
    opacity: 0.2;
  }
}

/* The deadline is the one mark that moves for a reason rather than because the
   window scrolled, so it is the one mark that eases into its new place. Short
   enough that the per-frame scroll still reads as continuous. */
.strip__deadline {
  position: absolute;
  top: 8px;
  bottom: 22px;
  width: 1px;
  background: var(--speech);
  opacity: 0.45;
  transition: left var(--tempo-quick) var(--ease-out);
}

/* The label hangs to the left of its line: the deadline can sit near the right
   edge, and a label drawn outward from there is cut off. */
.strip__deadline::after {
  content: 'deadline';
  position: absolute;
  top: 0;
  right: 4px;
  font-family: var(--face-data);
  font-size: 0.6875rem;
  color: var(--speech);
}

.strip__now {
  position: absolute;
  top: 0;
  bottom: 22px;
  width: 1px;
  background: var(--ink);
}

/* A gradient cannot be transitioned, so the hatch lives in an overlay whose
   opacity can. Fading it in reads as the bot standing down; switching it on
   reads as a glitch. */
.strip::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--tempo) var(--ease-out);
  background: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 6px,
    var(--sheet) 6px,
    var(--sheet) 12px
  );
}

.strip--paused::after {
  opacity: 1;
}

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

button {
  font-family: var(--face-data);
  font-size: 0.875rem;
  /* 14px of type on 12px of padding clears 40px of height, which is the floor
     for a finger on a phone. */
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--sheet);
  cursor: pointer;
  transition:
    background-color var(--tempo-quick) var(--ease-out),
    transform var(--tempo-tap) var(--ease-out);
}

/* Press has to weigh more than hover, or the control feels dead under a
   finger, where hover never happens at all. */
button:hover {
  background: var(--speech);
  border-color: var(--speech);
}

button:active {
  transform: translateY(1px);
}

button.secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule);
}

button.secondary:hover {
  background: var(--paper);
  border-color: var(--ink);
  color: var(--ink);
}

button.secondary[aria-pressed='true'] {
  background: var(--speech);
  border-color: var(--speech);
  color: var(--sheet);
}

.counters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  margin: var(--space-6) 0 0;
  padding-top: var(--space-5);
  border-top: 1px solid var(--rule);
}

.counters div {
  display: flex;
  flex-direction: column-reverse;
  gap: var(--space-1);
}

.counters dt {
  font-family: var(--face-data);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--graphite);
}

.counters dd {
  margin: 0;
  font-family: var(--face-data);
  font-size: var(--size-section);
  /* Tabular figures: the counters change while you watch, and proportional
     digits would shift the label under every update. */
  font-variant-numeric: tabular-nums;
}

@keyframes land {
  from {
    opacity: 0.45;
    transform: translateY(-2px);
  }
}

.counters dd.changed {
  animation: land var(--tempo) var(--ease-out);
}

.log {
  font-family: var(--face-data);
  font-size: 0.8125rem;
  line-height: 1.9;
  list-style: none;
  margin: var(--space-5) 0 0;
  padding: var(--space-3) 0 0;
  border-top: 1px solid var(--rule);
  height: 132px;
  overflow-y: auto;
  color: var(--graphite);
}

.log__empty {
  color: var(--graphite);
}

@keyframes log-line {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
}

.log li {
  animation: log-line var(--tempo-quick) var(--ease-out);
}

.log b {
  color: var(--ink);
  font-weight: 500;
}

.log em {
  color: var(--speech);
  font-style: normal;
}

/* Policy ------------------------------------------------------------------ */

.instrument__note {
  margin: 0;
  max-width: 64ch;
  font-family: var(--face-data);
  font-size: 0.6875rem;
  line-height: 1.7;
  color: var(--graphite);
}

/* Three faders rather than three fields. What is worth knowing about quietMs
   is not the number, it is what the deadline does while the number moves, and
   a value you drag is the only control that shows you that. The ends of each
   track say what the range is, so nothing has to write it down. */
.faders {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.faders__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

/* A button that is a word in a sentence, so it undoes what the page gives a
   button and takes what it gives a link instead. */
.faders__restore {
  font-family: var(--face-data);
  font-size: 0.6875rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--speech);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.faders__restore:hover {
  background: none;
  color: var(--ink);
}

.fader {
  display: grid;
  grid-template-columns: 13ch minmax(0, 1fr) 9ch;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--face-data);
  font-size: 0.75rem;
}

.fader__name {
  color: var(--graphite);
}

.fader__value {
  text-align: right;
  /* Tabular figures: the value changes under a dragging finger, and
     proportional digits would shift the column while it did. */
  font-variant-numeric: tabular-nums;
}

/* The track is a hairline and the thumb is a square, because every other
   object on this page is one or the other. Both vendors need their own
   selectors, and a rule either browser cannot parse drops the whole block, so
   the two are never written together. */
.fader__input {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 18px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}

.fader__input::-webkit-slider-runnable-track {
  height: 2px;
  background: linear-gradient(
    to right,
    var(--speech) 0,
    var(--speech) var(--fill, 0%),
    var(--rule) var(--fill, 0%)
  );
}

.fader__input::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 8px;
  height: 16px;
  /* Half the thumb, less half the track, so it sits centred on the hairline. */
  margin-top: -7px;
  border: 0;
  border-radius: 0;
  background: var(--ink);
}

.fader__input::-moz-range-track {
  height: 2px;
  background: var(--rule);
}

.fader__input::-moz-range-progress {
  height: 2px;
  background: var(--speech);
}

.fader__input::-moz-range-thumb {
  width: 8px;
  height: 16px;
  border: 0;
  border-radius: 0;
  background: var(--ink);
}

.fader__input:hover::-webkit-slider-thumb,
.fader__input:focus::-webkit-slider-thumb {
  background: var(--speech);
}

.fader__input:hover::-moz-range-thumb,
.fader__input:focus::-moz-range-thumb {
  background: var(--speech);
}

/* Conversation ------------------------------------------------------------ */

/* Two views of one run. The conversation is what the person sees and the strip
   is what the runtime sees, so they sit side by side rather than one under the
   other: the whole point is that a keystroke on the left moves a marker on the
   right, and a reader who has to scroll between them never catches it. */
.instrument__grid {
  display: grid;
  grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
  gap: var(--space-6);
  align-items: stretch;
}

.chat {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--rule);
  background: var(--paper);
}

.chat__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--rule);
}

.chat__state {
  font-family: var(--face-data);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  color: var(--graphite);
}

.chat__state[data-state='paused'] {
  color: var(--speech);
}

/* The basis rather than a height: on a wide screen the row is as tall as the
   strip column beside it and the thread takes the difference, and on a narrow
   one it keeps its own size and scrolls. */
.chat__thread {
  flex: 1 1 300px;
  min-height: 0;
  overflow-y: auto;
  list-style: none;
  margin: 0;
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* The thread fills from the bottom, the way a conversation does. The auto
   margin does it rather than justify-content, which in a scrolling flex column
   puts the oldest messages out of reach once the thread overflows. */
.chat__thread > :first-child {
  margin-top: auto;
}

.chat__empty {
  color: var(--graphite);
  font-size: 0.9375rem;
  margin: 0;
}

/* One group is one run of balloons that will become one turn. It is the only
   element on the page whose height is animated, and only at the moment the
   balloons inside it are replaced by the block they became. */
.chat__group {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-2);
  overflow: hidden;
  transition: height var(--tempo-speak) var(--ease-out);
}

.balloon {
  max-width: 85%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--rule);
  background: var(--sheet);
  font-family: var(--face-data);
  font-size: 0.8125rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
  animation: arrive var(--tempo-quick) var(--ease-out);
}

/* A dropped balloon stays legible. It was received, it was read, and then it
   was refused; greying it out and saying why is the whole story. */
.balloon--dropped {
  border-style: dashed;
  background: transparent;
  color: var(--graphite);
}

.balloon__tag {
  display: block;
  margin-top: var(--space-1);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--graphite);
}

/* The countdown under the open group. It is the deadline written out in words
   and a bar that drains toward it, and both restart when a keystroke pushes
   the deadline back, which is the one thing a still image cannot show. */
.chat__wait {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: var(--space-2);
  font-family: var(--face-data);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--graphite);
}

.chat__wait-left {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.chat__wait-bar {
  grid-column: 1 / -1;
  height: 2px;
  background: var(--rule);
}

.chat__wait-bar i {
  display: block;
  height: 100%;
  background: var(--speech);
  transform-origin: left center;
  /* Slightly longer than the tick that sets it, so the drain reads as one
     movement rather than ten steps a second. */
  transition: transform var(--tempo-quick) linear;
}

/* The inversion the palette exists for, in the second place it can happen: the
   balloons leave and this arrives in their place. */
.chat__turn {
  width: 100%;
  padding: var(--space-3);
  background: var(--speech);
  color: var(--sheet);
  font-family: var(--face-data);
  animation: speak var(--tempo-speak) var(--ease-out);
  transform-origin: bottom;
}

.chat__turn-head {
  display: block;
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.72;
  margin-bottom: var(--space-2);
}

.chat__turn-text {
  display: block;
  font-size: 0.8125rem;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

.chat__turn-line {
  display: block;
}

/* Three dots would be a second expressive device on a page that decided to
   have one. The chip says it in the same voice as everything else. */
.chat__typing {
  margin: 0;
  padding: 0 var(--space-4) var(--space-2);
  font-family: var(--face-data);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--speech);
  animation: arrive var(--tempo-quick) var(--ease-out);
}

.chat__typing[hidden] {
  display: none;
}

.composer {
  display: flex;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-top: 1px solid var(--rule);
}

.composer input {
  flex: 1;
  min-width: 0;
  font-family: var(--face-data);
  font-size: 0.875rem;
  padding: var(--space-3);
  border: 1px solid var(--rule);
  background: var(--sheet);
  color: var(--ink);
}

.composer input::placeholder {
  color: var(--graphite);
}

button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

button.secondary:disabled:hover {
  background: transparent;
  border-color: var(--rule);
}

/* Below this the two views stack, and the conversation goes first: it is the
   one the visitor types into. */
@media (max-width: 900px) {
  .instrument__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-5);
  }

  .chat__thread {
    flex-basis: 240px;
  }
}

/* Prose sections ---------------------------------------------------------- */

.section {
  padding: var(--space-8) 0;
  border-top: 1px solid var(--rule);
}

.section h2 {
  font-size: var(--size-title);
  margin-bottom: var(--space-5);
}

.section h3 {
  font-size: var(--size-lead);
  margin: var(--space-6) 0 var(--space-2);
}

.section p {
  margin: 0 0 var(--space-4);
}

.rule-panel {
  font-family: var(--face-data);
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--space-5);
  margin: var(--space-5) 0;
  overflow-x: auto;
}

pre {
  font-family: var(--face-data);
  font-size: 0.875rem;
  line-height: 1.7;
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--space-5);
  overflow-x: auto;
  margin: 0 0 var(--space-4);
}

.figures {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-7);
  margin: var(--space-6) 0 0;
  padding: 0;
}

.figures div {
  display: flex;
  flex-direction: column-reverse;
}

.figures dt {
  font-family: var(--face-data);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--graphite);
}

.figures dd {
  margin: 0;
  font-family: var(--face-data);
  font-size: var(--size-title);
  /* Tabular figures are load-bearing here: these numbers run from zero to
     20,888, and proportional digits would make the whole row breathe in and
     out while they counted. */
  font-variant-numeric: tabular-nums;
}

/* The row lifts while it counts, so the rise and the numbers are one gesture
   driven by one trigger. The class arrives from figures.js, the same place the
   counting starts, rather than from a second mechanism that could fall out of
   step with it. */
@keyframes lift {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

.figures div.counting {
  animation: lift var(--tempo) var(--ease-out) both;
}

footer {
  border-top: 1px solid var(--rule);
  padding: var(--space-6) 0 var(--space-8);
  font-family: var(--face-data);
  font-size: 0.8125rem;
  color: var(--graphite);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  justify-content: space-between;
}

/* Narrow screens. The instrument keeps its height; only the padding and the
   hero line give way. */
@media (max-width: 640px) {
  .instrument {
    padding: var(--space-4);
  }

  .hero {
    padding: var(--space-7) 0 var(--space-6);
  }

  .counters,
  .figures {
    gap: var(--space-5);
  }
}

/* Everything above is optional. Under a reduced-motion preference the page
   still reports every state; it simply stops moving between them. */
@media (prefers-reduced-motion: reduce) {
  .chat__wait-bar {
    display: none;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
  }
}
