/* ============================================================
   Markdown To — the playground  (site/app/index.html)

   The workbench of the same publication. ../styles.css loads
   first and carries the whole system — the typography, the
   vermillion, the tokens, the inked plate — and this file adds
   only the bench: a control rail, two panes, and the status line
   between them.

   Light is the primary design; the dark block at the end is the
   automatic prefers-color-scheme variant, derived from it. Every
   token used here is one ../styles.css already defines, so a
   value tuned there stays tuned here.

   Two rules govern the layout:

     · The page never scrolls sideways. The editor scrolls inside
       its textarea, the rendered document scrolls inside its
       iframe, and the rail wraps.
     · The panes are side by side from 900px and stacked below it,
       where a segmented control chooses which one is on screen —
       two half-width panes on a phone would be two useless panes.

   No arrow glyphs: the subset fonts have none.
   ============================================================ */

/* ------------------------------------------------------------
   0. Bench-only tokens
   ------------------------------------------------------------ */
:root {
  /* The editor's metrics live in variables because the gutter has
     to agree with the textarea to the pixel — one line-height,
     one font-size, one top padding, read by both. */
  --ed-size: 0.8rem;
  --ed-line: 1.75;
  --ed-pad-y: 1rem;
  --ed-gutter: 3.1rem;

  /* The bench runs wider than the publication's --wide (74rem).
     It is not a column of prose: the rendered pane has to clear
     44rem on its own, because that is the width at which the
     renderers lay a board out as columns rather than stacking it —
     and a playground for a board format that cannot show a board
     side by side with its source has missed the point. The topbar
     and the colophon are widened to match so the page still reads
     as one measure. */
  --bench: min(100%, 92rem);

  /* A resolved severity palette, matching specs/specs.css. */
  --sev-ok:    #2f6a3f;
  --sev-warn:  #8a5f0e;
  --sev-err:   var(--acc);
  --tint-ok:   #eef5ef;
  --tint-warn: #faf3e6;
}

/* The bench is a fixed-height application surface, not an
   article: the panes fill what is left of the viewport rather
   than growing a page that scrolls past them. */
.app { min-height: 100dvh; display: flex; flex-direction: column; }
.app .foot { margin-top: auto; padding-top: clamp(1.6rem, 3vw, 2.4rem); }

.app .topbar__in,
.app .foot__rule { max-width: var(--bench); }

.bench {
  width: 100%;
  max-width: var(--bench);
  margin-inline: auto;
  padding: clamp(1.4rem, 3.4vw, 2.6rem) clamp(1rem, 4vw, 2.5rem) clamp(1.6rem, 3vw, 2.4rem);
  display: flex;
  flex-direction: column;
  gap: clamp(.9rem, 1.8vw, 1.25rem);
}

/* ------------------------------------------------------------
   1. Head
   ------------------------------------------------------------ */
.bench__head { max-width: 54rem; }
.bench__title {
  font-size: clamp(2rem, 1.3rem + 2.6vw, 3.1rem);
  line-height: 1.02;
  letter-spacing: -.024em;
  font-weight: 400;
  text-wrap: balance;
}
.bench__lede {
  margin-top: .75rem;
  max-width: 46rem;
  font-size: .98rem;
  line-height: 1.55;
  color: var(--ink-2);
}
.bench__lede em { font-style: italic; color: var(--ink); }

/* ------------------------------------------------------------
   2. Control rail
   ------------------------------------------------------------ */
.rail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .7rem 1.1rem;
  margin-top: clamp(.4rem, 1.4vw, .9rem);
}
.rail__set { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.rail__set--end { margin-left: auto; }
.rail__lbl {
  font-family: var(--font-mono);
  font-size: .6rem;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* the four template buttons, as one segmented control */
.seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: .25rem;
  background: var(--paper-3);
  border-radius: 100px;
  padding: .26rem;
}
.seg__b {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: -.005em;
  color: var(--ink-2);
  padding: .38rem .85rem;
  border-radius: 100px;
  transition: color .18s, background .18s, box-shadow .18s;
}
.seg__b:hover { color: var(--ink); }
.seg__b[aria-pressed="true"] {
  color: var(--ink);
  background: var(--card);
  font-weight: 500;
  box-shadow: var(--shadow-s), var(--ring);
}

/* Open / Download. `.pill` is `.btn` at the rail's scale — the
   label wraps a hidden file input, which is why it is a label. */
.pill {
  position: relative;          /* holds the visually hidden file input */
  display: inline-block;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .005em;
  padding: .52rem 1.05rem;
  border-radius: 100px;
  background: var(--card);
  color: var(--ink-2);
  box-shadow: var(--shadow-s), var(--ring);
  transition: box-shadow .22s cubic-bezier(.2,.8,.3,1),
              transform .22s cubic-bezier(.2,.8,.3,1), color .2s, background .2s;
}
.pill:hover { color: var(--ink); box-shadow: var(--shadow-m), var(--ring); transform: translateY(-1px); }
.pill:has(input:focus-visible) { outline: 2px solid var(--acc); outline-offset: 3px; }
.pill input[type="file"] {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; overflow: hidden; clip: rect(0 0 0 0);
}
.pill--go { color: var(--acc); background: var(--tint); }
.pill--go:hover { color: var(--acc); }

/* Present carries a mark because it is the one control on the rail
   that changes what the *page* is rather than what the file is.
   Four corner brackets, drawn — the subset fonts have no glyph for
   this and every mark on this site is a path. */
.pill--present { display: inline-flex; align-items: center; gap: .5rem; }
.pill--present[aria-pressed="true"] { color: var(--ink); background: var(--paper-3); }
.pill__i {
  width: .86em;
  height: .86em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ------------------------------------------------------------
   3. Status line — always visible, whatever the file is doing
   ------------------------------------------------------------ */
.status {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .5rem .7rem;
  min-height: 2.1rem;
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .01em;
  color: var(--ink-2);
}
.sev {
  font-size: .62rem;
  letter-spacing: .13em;
  text-transform: uppercase;
  padding: .26rem .68rem .22rem;
  border-radius: 100px;
  font-weight: 600;
  white-space: nowrap;
}
.sev--ok    { color: var(--sev-ok);   background: var(--tint-ok); }
.sev--warn  { color: var(--sev-warn); background: var(--tint-warn); }
.sev--error { color: var(--sev-err);  background: var(--tint); }
.status__spec { color: var(--ink); font-weight: 500; }
/* The jump control is a real button: it moves the caret to the
   line and column the diagnostic names. */
.jump {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--acc);
  border-radius: var(--r-xs);
  padding: .1rem .15rem;
  text-decoration: underline;
  text-decoration-color: var(--acc-line);
  text-underline-offset: .2em;
}
.jump:hover { text-decoration-color: var(--acc); }

/* ------------------------------------------------------------
   4. The pane switch (narrow screens only)
   ------------------------------------------------------------ */
.swap {
  display: inline-flex;
  gap: .25rem;
  background: var(--paper-3);
  border-radius: 100px;
  padding: .26rem;
  width: fit-content;
}
.swap__b {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--ink-2);
  padding: .4rem 1.1rem;
  border-radius: 100px;
  transition: color .18s, background .18s, box-shadow .18s;
}
.swap__b[aria-pressed="true"] {
  color: var(--ink);
  background: var(--card);
  font-weight: 500;
  box-shadow: var(--shadow-s), var(--ring);
}
@media (min-width: 900px) { .swap { display: none; } }

/* ------------------------------------------------------------
   5. The two panes
   ------------------------------------------------------------ */
.panes {
  display: grid;
  gap: clamp(.9rem, 2vw, 1.4rem);
  grid-template-columns: minmax(0, 1fr);
  /* Tall enough to work in, short enough that the hint under it
     stays on screen. dvh so a phone's collapsing toolbar does not
     leave the bottom of the board under it. */
  height: clamp(24rem, 62dvh, 44rem);
}
/* The editor column is sized backwards from the rendered pane: it
   takes what is left after the frame has enough room to draw a
   board as columns (44rem inside the renderer's own stylesheet).
   Below that the board stacks, which is the renderer being right
   about a narrow viewport, not this page being wrong. */
@media (min-width: 900px) {
  .panes {
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    height: clamp(26rem, 66dvh, 48rem);
  }
}
@media (min-width: 1200px) { .panes { grid-template-columns: minmax(0, 24rem) minmax(0, 1fr); } }
@media (min-width: 1440px) { .panes { grid-template-columns: minmax(0, 30rem) minmax(0, 1fr); } }

/* Below 900px exactly one pane is on screen at a time. */
@media (max-width: 899px) {
  .panes[data-show="edit"] .pane--view,
  .panes[data-show="view"] .pane--edit { display: none; }
}

.pane {
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r);
  background: var(--card);
  box-shadow: var(--shadow-m), var(--ring);
}
/* The source pane is inked in both schemes, like every code plate
   on this site: a dark card is what makes a file read as a file. */
.pane--edit { background: var(--plate); box-shadow: var(--shadow-m); }

.pane__bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .62rem .95rem;
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .02em;
  color: var(--ink-3);
  border-bottom: 1px solid var(--rule-soft);
}
.pane__bar--ink { color: var(--plate-dim); border-bottom-color: var(--plate-rule); }
.pane__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--plate-acc); flex: none; }
.pane__name { font-size: .62rem; letter-spacing: .12em; text-transform: uppercase; font-weight: 500; }
.pane__meta,
.pane__tag {
  margin-left: auto;
  font-size: .6rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.pane__tag {
  color: var(--ink-3);
  background: var(--paper-2);
  border-radius: 100px;
  padding: .18rem .58rem .14rem;
}

/* the editable file name, drawn as text until you touch it */
.fname {
  flex: 1 1 8rem;
  min-width: 0;
  font: inherit;
  font-weight: 500;
  color: var(--plate-fg);
  background: none;
  border: 0;
  border-radius: var(--r-xs);
  padding: .12rem .3rem;
  margin-left: -.3rem;
  transition: background .18s;
}
.fname:hover { background: var(--plate-2); }
.fname:focus { background: var(--plate-2); outline: 2px solid var(--plate-acc); outline-offset: 1px; }

/* ---------- the editor ---------- */
.ed {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
}
/* The gutter is painted under the textarea and scrolled with it
   by app.js. It is aria-hidden: the line numbers are an aid to
   the eye, and a screen reader reading "1 2 3 4" over a document
   it is already reading is noise. */
.ed__gutter {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--ed-gutter);
  overflow: hidden;
  padding: var(--ed-pad-y) .7rem var(--ed-pad-y) 0;
  font-family: var(--font-mono);
  font-size: var(--ed-size);
  line-height: var(--ed-line);
  font-variant-numeric: lining-nums tabular-nums;
  text-align: right;
  color: var(--plate-dim);
  background: var(--plate-2);
  border-right: 1px solid var(--plate-rule);
  white-space: pre;
  pointer-events: none;
}
.ed__area {
  flex: 1;
  min-width: 0;
  display: block;
  resize: none;
  border: 0;
  background: none;
  color: var(--plate-fg);
  caret-color: var(--plate-acc);
  font-family: var(--font-mono);
  font-size: var(--ed-size);
  line-height: var(--ed-line);
  font-variant-numeric: lining-nums;
  tab-size: 2;
  padding: var(--ed-pad-y) 1.1rem var(--ed-pad-y) calc(var(--ed-gutter) + .8rem);
  overflow: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--plate-dim) transparent;
}
.ed__area:focus { outline: 0; }
.ed__area::selection { background: var(--plate-acc); color: #fff; }
.ed:focus-within { box-shadow: inset 0 0 0 2px var(--plate-acc); }

/* The one moment the whole page exists for: a card is dragged in
   the frame, the patch engine writes the file, and the text on
   this side changes. Without a cue it happens off the eye's beat. */
.pane--edit.is-patched .ed { animation: patched 1.05s cubic-bezier(.2,.7,.3,1); }
@keyframes patched {
  0%   { box-shadow: inset 0 0 0 2px var(--plate-acc); background: rgba(239, 113, 72, .11); }
  100% { box-shadow: inset 0 0 0 2px transparent; background: transparent; }
}

/* ---------- the rendered stage ---------- */
.stage {
  flex: 1;
  min-height: 0;
  width: 100%;
  border: 0;
  display: block;
  background: var(--paper);
  color-scheme: light dark;
}

/* ------------------------------------------------------------
   6. Present — the rendered view, and the window

   The meeting test: open the page, build a board, share the
   screen. Everything here except the frame is scaffolding for
   *writing* the file — the masthead, the lede, the rail, the
   status line, the gutter, the pane titles — and an audience
   needs none of it, so presenting takes all of it off and gives
   the frame the viewport. What is left is one pair of buttons in
   a corner at a third of full opacity.

   Nothing moves in the DOM and the frame is never re-mounted, so
   a board keeps its scroll and its selection across the switch.
   The editor is *parked*, not hidden: it becomes a drawer that
   starts off the left edge with its layout intact, because a
   `display: none` textarea loses the scrollTop and the selection
   that §6 of app.js exists to protect — and a card dragged while
   presenting still writes into it.

   Every rule below outranks §5's narrow-viewport pane switch on
   specificity, which is the point: presenting shows the document
   whichever pane the switch last chose, and leaves the switch
   set as it was for the way back.
   ------------------------------------------------------------ */
.pres { display: none; }

.is-present { overflow: hidden; }
.is-present .topbar,
.is-present .bench__head,
.is-present .rail,
.is-present .status,
.is-present .swap,
.is-present .hint,
.is-present .foot { display: none; }
.is-present .bench { padding: 0; gap: 0; }

.is-present .panes {
  position: fixed;
  inset: 0;
  z-index: 90;
  height: 100dvh;
  gap: 0;
  grid-template-columns: minmax(0, 1fr);
}
.is-present .panes .pane--view {
  display: flex;
  border-radius: 0;
  box-shadow: none;
}
.is-present .panes .pane--view .pane__bar { display: none; }

.is-present .panes .pane--edit {
  display: flex;
  position: fixed;
  z-index: 95;
  top: clamp(.6rem, 1.4vw, 1rem);
  bottom: clamp(.6rem, 1.4vw, 1rem);
  left: clamp(.6rem, 1.4vw, 1rem);
  width: min(30rem, 86vw);
  border-radius: var(--r);
  box-shadow: var(--shadow-l);
  transform: translateX(calc(-100% - 1.6rem));
  transition: transform .34s cubic-bezier(.2, .8, .3, 1);
}
.is-present.is-drawer .panes .pane--edit { transform: none; }
/* On a phone the drawer is nearly the width of the screen, so it
   stops short of the bottom rather than burying the way out. */
@media (max-width: 899px) {
  .is-present .panes .pane--edit { bottom: 3.6rem; }
}

/* The corner cluster. At rest it is barely there; a pointer over
   it, or a focus ring inside it, brings it up. */
.is-present .pres {
  display: flex;
  gap: .22rem;
  position: fixed;
  z-index: 100;
  right: clamp(.7rem, 1.6vw, 1.15rem);
  bottom: clamp(.7rem, 1.6vw, 1.15rem);
  padding: .26rem;
  border-radius: 100px;
  /* It floats over a document it knows nothing about — a white
     card, an inked plate — so it carries its own ground. */
  background: color-mix(in srgb, var(--card) 86%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: var(--shadow-m), var(--ring);
  opacity: .32;
  transition: opacity .24s;
}
.is-present .pres:hover,
.is-present .pres:focus-within { opacity: 1; }
.pres__b {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .02em;
  color: var(--ink-2);
  padding: .42rem 1rem;
  border-radius: 100px;
  transition: color .18s, background .18s;
}
.pres__b:hover { color: var(--ink); background: var(--paper-2); }
.pres__b[aria-pressed="true"] { color: var(--ink); background: var(--paper-3); font-weight: 500; }
.pres__b--out { color: var(--acc); }
.pres__b--out:hover { color: var(--acc); background: var(--tint); }

/* ------------------------------------------------------------
   7. Hint + drop curtain
   ------------------------------------------------------------ */
.hint {
  font-size: .88rem;
  line-height: 1.55;
  color: var(--ink-3);
  max-width: 58rem;
}
.hint b { color: var(--ink-2); }
.hint--warn {
  background: var(--tint-warn);
  border-radius: var(--r);
  padding: 1rem 1.2rem;
  color: var(--ink-2);
}

.drop {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  place-items: center;
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.dropping .drop { display: grid; }
.drop span {
  font-family: var(--font-mono);
  font-size: .84rem;
  letter-spacing: .04em;
  color: var(--ink);
  background: var(--card);
  border-radius: var(--r);
  padding: 1.5rem 2.2rem;
  box-shadow: var(--shadow-l), inset 0 0 0 2px var(--acc-line);
}
.drop code { background: none; color: var(--acc); }

/* ------------------------------------------------------------
   8. Footer, trimmed for a tool page
   ------------------------------------------------------------ */
.app .foot__rule { border-top: 1px solid var(--rule-soft); }
.app .foot__rule a { color: inherit; text-decoration: none; }
.app .foot__rule a:hover { color: var(--acc); }

/* ------------------------------------------------------------
   9. Dark — derived from the light design above
   ------------------------------------------------------------ */
@media (prefers-color-scheme: dark) {
  :root {
    --sev-ok:    #8fbf9c;
    --sev-warn:  #d9b063;
    --tint-ok:   #16211a;
    --tint-warn: #241d10;
  }
  /* On near-black the inked pane needs its hairline back: a
     shadow separates nothing there. */
  .pane--edit { box-shadow: var(--shadow-m), inset 0 0 0 1px var(--plate-rule); }
  .is-present .panes .pane--edit { box-shadow: var(--shadow-l), inset 0 0 0 1px var(--plate-rule); }
  /* On near-black a third of an opacity is nearly nothing; the
     cluster has to stay findable without being lit. */
  .is-present .pres { opacity: .42; }
  .drop { background: color-mix(in srgb, var(--paper) 78%, transparent); }
}

/* ------------------------------------------------------------
   10. Reduced motion
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  /* The patch cue still has to land — it is information, not
     decoration — so it becomes a static hold rather than a fade. */
  .pane--edit.is-patched .ed { animation: none; box-shadow: inset 0 0 0 2px var(--plate-acc); }
}
