/* ==============================================================
   DRAFTING-WIDGET.CSS — shared engine stylesheet
   Extracted from the five per-document widgets (go ENGINE-EXTRACT,
   2026-05-28). One stylesheet for every drafting document; the
   per-document data lives in its manifest (drafting/*.js).
   ============================================================== */

/* ==================================================================
   WRIT OF SUMMONS — DRAFTING WIDGET (first finished drafting deliverable)
   Civil Procedure · CI 47 Form 1 · Order 2 rule 3(1) (verbatim wording)
   Cross-checked against Francisca Drafting Precedents p.898 (Precedent 1).
   Civil Pro DRAFTINGS does NOT include a Writ — it begins at Statement of
   Claim, so only Francisca + CI 47 contribute here. No source gap.

   Three modes: Raw · Decoded · Assemble.
   Six colour zones: CROWN · PARTIES · ADDRESS · RECITAL · COMMAND · WARNING.
   Mobile bottom-sheet replaces side-by-side decoder pane (also used on
   desktop focus mode). Drag-and-drop active-recall via pointer events.
   ================================================================== */

:root {
  /* Paper surface — readable in any theme */
  --paper:        #fbf7ec;
  --paper-2:      #f3eddb;
  --paper-edge:   #c9bda1;
  --paper-ink:    #1a1410;
  --paper-rule:   rgba(0,0,0,0.10);
  --seal-gold:    #b08a2e;
  --seal-gold-2:  #876618;

  /* Zone tints — pastel base + bolder accent */
  --z-crown:      #fdebbf; --z-crown-2:   #a8761a;
  --z-parties:    #d4ebcf; --z-parties-2: #2f6e34;
  --z-address:    #d2e6f3; --z-address-2: #1c5778;
  --z-recital:    #e3d5f0; --z-recital-2: #5b3a8a;
  --z-command:    #fad0b3; --z-command-2: #a44a18;
  --z-warning:    #f5c9c9; --z-warning-2: #9a2a2a;
  --z-indorse:    #cce7e0; --z-indorse-2: #1c7a66;   /* 7th slot — indorsement of claim (writ, O.2 r 3(1)); additive, 6-zone docs never reference it */

  /* Spring easings */
  --spring:       cubic-bezier(0.34, 1.56, 0.64, 1);
  --soft:         cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- Mode toggle + bar ---------- */
.widget-bar {
  display: flex; flex-wrap: wrap; gap: 10px 14px;
  /* align-items:flex-start so the mode pill anchors to the TOP of the bar; when
     the meta chips / actions wrap below it (mobile), the pill stays put at the
     top-left rather than floating centred against the wrapped rows.
     justify-content removed — .bar-actions uses margin-left:auto so TOUR + the
     expand toggle always sit LAST, hard against the right edge. */
  align-items: flex-start;
  margin: 14px 0 14px;
  /* Papa 2026-06-01: NOT sticky — it scrolls away with the page; the reader can
     scroll back up if they need Raw/Decoded/Assemble. Frees screen for the doc. */
  position: relative;
  background: var(--bg);
  /* Comfortable side padding so the mode pill and the CI 47 chip don't
     butt right up against the container's edge. */
  padding: 7px 16px;
  border-bottom: 1px solid var(--hairline);
  border-radius: 10px;
}
/* Solid mask strip below the sticky toolbar — fully opaque cream so anything
   scrolling behind it (the previous decoder card's bottom edge in the
   breathing-room gap) is completely hidden, with NO fade seam. Same colour
   as the page bg so the bar reads as smoothly continuous with the page. */
.widget-bar::after {
  content: '';
  position: absolute;
  /* Height matches the bar's bottom margin (14px) so in the un-scrolled state
     the mask fills the margin gap EXACTLY and never overlaps the top border /
     rounded corner of the story-anchor card directly below it. When the bar is
     pinned and content scrolls under it, this same band hides the seam. */
  top: 100%; left: 0; right: 0;
  height: 14px;
  background: var(--bg);
  pointer-events: none;
}
.mode-pill {
  position: relative;
  display: inline-flex; align-items: center; gap: 0;
  background: var(--bg-elev); border: 1px solid var(--hairline-2);
  border-radius: 999px; padding: 4px;
  align-self: flex-start;  /* sticks to the top of the bar (Papa 2026-05-31) */
  flex-shrink: 0;
}

/* Action cluster — TOUR + expand toggle (+ live tour counter). margin-left:auto
   shoves it to the far right so it always reads as the LAST item on the bar. */
.bar-actions {
  display: inline-flex; align-items: center; gap: 10px;
  margin-left: auto; flex-shrink: 0;
  align-self: center;
}
.mode-pill button {
  appearance: none; background: transparent; color: var(--ink-muted); border: 0;
  font: 700 0.78rem var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase;
  padding: 7px 16px; border-radius: 999px; cursor: pointer;
  transition: color 200ms var(--soft);
  position: relative; z-index: 2;
}
.mode-pill button[aria-pressed="true"] { color: var(--cta-ink); }
.mode-pill .pill-thumb {
  position: absolute; top: 4px; bottom: 4px; left: 4px;
  background: var(--ink); border-radius: 999px;
  transition: transform 350ms var(--spring), width 350ms var(--spring);
  z-index: 1;
}

.widget-meta {
  /* nowrap keeps the CI 47 citation chip and the "Best" time chip on the SAME
     line (Papa 2026-05-31) instead of stacking. align-self:center vertically
     centres the chips against the top-anchored mode pill on the desktop row. */
  display: flex; gap: 10px; align-items: center; flex-wrap: nowrap;
  align-self: center; min-width: 0;
  color: var(--ink-muted); font-size: 0.82rem; font-family: var(--font-body);
}

/* MOBILE/narrow reflow: the two info chips drop to their own full-width row
   (staying together), while the mode pill + TOUR share the top row. */
@media (max-width: 980px) {
  .widget-meta { order: 3; flex: 1 0 100%; }
  .bar-actions { order: 2; }
  /* keep the document switcher last on its own row (it defaults to order 0,
     which would otherwise hoist it above the re-ordered chips/actions). */
  .dw-doc-switch { order: 4; }
}
.widget-meta .chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg-elev); border: 1px solid var(--hairline);
  padding: 5px 10px; border-radius: 999px;
  font: 600 0.72rem var(--font-mono); letter-spacing: 0.08em;
  color: var(--ink-muted);
}
.widget-meta .chip svg { width: 13px; height: 13px; }

/* Phone: compress the whole control bar so the drafting document gets the room.
   Same rows, but each is tighter — smaller mode pill, CI 47 chip and document
   switcher, less padding/margin — so the sticky bar steals far less height.
   Papa 2026-06-01. */
@media (max-width: 640px) {
  /* NO top: offset — the bar is position:relative (not sticky, Papa 2026-06-01),
     so a stray top:60px (leftover from the sticky era) shifted the rendered bar
     DOWN 60px while its flow box stayed put, dropping it onto the link-story card
     below by ~50px. Removed so the bar sits exactly where it flows. */
  .widget-bar { padding: 5px 10px; gap: 5px 8px; margin: 10px 0; border-radius: 8px; }
  .widget-bar::after { height: 10px; }
  .mode-pill { padding: 3px; }
  .mode-pill button { padding: 5px 12px; font-size: 0.66rem; letter-spacing: 0.05em; }
  .bar-actions { gap: 6px; align-self: center; }
  .widget-meta { gap: 6px; }
  .widget-meta .chip { padding: 4px 8px; font-size: 0.62rem; letter-spacing: 0.04em; }
  .widget-meta .chip svg { width: 11px; height: 11px; }
  .dw-doc-switch { gap: 7px; padding-top: 7px; }
  .dw-ds-arrow { width: 32px; height: 32px; }
  .dw-ds-arrow svg { width: 17px; height: 17px; }
  .dw-ds-center { gap: 1px; }
  .dw-ds-kicker { font-size: 0.55rem; letter-spacing: 0.12em; }
  .dw-ds-select { padding: 6px 30px 6px 10px; font-size: 0.82rem; }
}

/* ---------- Linking story sentence ---------- */
.link-story {
  position: relative;
  background: linear-gradient(180deg, var(--bg-elev), var(--bg));
  border: 1px solid var(--hairline-2);
  border-radius: 16px;
  padding: 20px 24px 20px 28px;
  margin: 0 0 22px;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.6vw, 1.28rem);
  line-height: 1.55; font-style: italic;
  overflow: hidden;
}
.link-story::before {
  content: ''; position: absolute; left: 0; top: 12px; bottom: 12px; width: 4px;
  background: linear-gradient(180deg, var(--z-crown-2), var(--z-parties-2), var(--z-address-2), var(--z-recital-2), var(--z-command-2), var(--z-warning-2), var(--z-indorse-2));
  border-radius: 2px;
}
.link-story .ls-label {
  display: flex; align-items: center; gap: 8px;
  font: 600 0.68rem var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-muted); margin-bottom: 10px; font-style: normal;
}
.link-story .ls-label svg { width: 14px; height: 14px; opacity: 0.7; }
.link-story .z {
  font-weight: 700; font-style: normal; padding: 3px 9px; border-radius: 6px;
  font-family: var(--font-mono); font-size: 0.82em; letter-spacing: 0.08em;
  cursor: pointer; transition: transform 180ms var(--spring), box-shadow 180ms var(--soft);
  display: inline-block;
}
.link-story .z:hover { transform: translateY(-2px); box-shadow: 0 6px 14px -6px rgba(0,0,0,0.3); }
.z.crown   { background: var(--z-crown);   color: var(--z-crown-2);   }
.z.parties { background: var(--z-parties); color: var(--z-parties-2); }
.z.address { background: var(--z-address); color: var(--z-address-2); }
.z.recital { background: var(--z-recital); color: var(--z-recital-2); }
.z.command { background: var(--z-command); color: var(--z-command-2); }
.z.warning { background: var(--z-warning); color: var(--z-warning-2); }
.z.indorse { background: var(--z-indorse); color: var(--z-indorse-2); }

/* ---------- Two-pane layout ---------- */
.widget-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.8fr);
  gap: 28px;
  align-items: start;
  /* No transition on grid-template-columns — Chrome refuses to interpolate
     between mismatched track shapes (minmax → 0fr), leaving the layout
     stuck at the old values. Mode changes flip layout instantly. */
}
@media (max-width: 980px) { .widget-grid { grid-template-columns: 1fr; gap: 18px; } }

/* FOCUS pane — document fills the screen; decoder hidden behind a toggle */
.widget[data-pane="focus"] .widget-grid { grid-template-columns: minmax(0, 1fr); }
.widget[data-pane="focus"] .decoder { display: none; }

/* Assemble mode is the active-recall test — no peeking at the decoder while
   the writ is blank. Hiding the decoder also resolves the z-index/stacking
   battle with the floating tray on desktop. Using a single-column template
   (not "1fr 0fr") so the writ truly fills the available width. */
.widget[data-mode="assemble"] .widget-grid { grid-template-columns: minmax(0, 1fr); }
.widget[data-mode="assemble"] .decoder { display: none; }

/* Focus toggle button */
.pane-toggle {
  appearance: none; cursor: pointer;
  background: var(--bg-elev); border: 1px solid var(--hairline-2);
  color: var(--ink-muted);
  width: 38px; height: 38px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 200ms var(--soft), color 200ms var(--soft);
}
.pane-toggle:hover { background: var(--bg-sunk); color: var(--ink); }
.pane-toggle svg { width: 18px; height: 18px; }
.widget[data-pane="focus"] .pane-toggle { background: var(--ink); color: var(--cta-ink); border-color: var(--ink); }
@media (max-width: 980px) { .pane-toggle { display: none; } }

/* ---------- DOCUMENT PANE ---------- */
/* Both columns scroll together — sticky was making the writ pin to the top
   while the decoder scrolled past it, breaking the "writ-zone matches
   decoder-card at the same vertical level" sync that the user expects. */
.doc-stage { position: static; }

.doc {
  position: relative;
  background:
    radial-gradient(circle at 18% 12%, rgba(255,255,255,0.55), transparent 38%),
    radial-gradient(circle at 82% 88%, rgba(0,0,0,0.04), transparent 42%),
    linear-gradient(180deg, var(--paper), var(--paper-2));
  color: var(--paper-ink);
  border: 1px solid var(--paper-edge);
  border-radius: 8px;
  box-shadow:
    0 30px 60px -32px rgba(0,0,0,0.45),
    0 4px 14px -8px rgba(0,0,0,0.2),
    inset 0 0 0 1px rgba(255,255,255,0.5);
  padding: 56px 52px 46px;
  font-family: 'Times New Roman', Times, Georgia, serif;
  font-size: 14.5px; line-height: 1.55;
  overflow: hidden;
}
/* Subtle fibrous paper grain */
.doc::before {
  content: ''; position: absolute; inset: 0;
  background-image:
    radial-gradient(rgba(120,90,40,0.05) 1px, transparent 1px),
    radial-gradient(rgba(120,90,40,0.04) 1px, transparent 1px);
  background-size: 22px 22px, 31px 31px;
  background-position: 0 0, 10px 10px;
  pointer-events: none; opacity: 0.7;
}
.doc > * { position: relative; z-index: 1; }
@media (max-width: 560px) {
  .doc { padding: 36px 22px 30px; font-size: 13.5px; border-radius: 6px; }
}

.doc .precedent-tag {
  display: flex; justify-content: space-between; align-items: baseline;
  font-style: italic; font-size: 0.78rem; color: #6a594a;
  margin-bottom: 18px; padding-bottom: 10px;
  border-bottom: 1px solid rgba(120,90,40,0.18);
  font-family: 'Times New Roman', Times, serif;
}
.doc .precedent-tag .src-ref {
  font-family: var(--font-mono); font-size: 0.68rem;
  letter-spacing: 0.08em; color: #876b48; font-style: normal;
}

/* ---------- ZONES inside the document ---------- */
.doc .zone {
  position: relative;
  /* Top: 34px header room so the chip never overlaps the first line of
   *      writ content (the bug in Papa's screenshots).
   * Left: 28px so the colour stripe (5px @ left:6px) clears the content.
   * Right/Bottom: comfortable margins. */
  padding: 34px 16px 14px 28px;
  margin: 10px -14px;
  border-radius: 6px;
  transition:
    background 280ms var(--soft),
    box-shadow 220ms var(--soft),
    transform 220ms var(--spring);
  cursor: pointer;
}

/* Per-zone CSS variable so the stripe + chip + colours can be set in one place
   and reused by ::before/::after rules without per-zone duplication. */
.doc .zone[data-zone="crown"]   { --zs: var(--z-crown-2);   }
.doc .zone[data-zone="parties"] { --zs: var(--z-parties-2); }
.doc .zone[data-zone="address"] { --zs: var(--z-address-2); }
.doc .zone[data-zone="recital"] { --zs: var(--z-recital-2); }
.doc .zone[data-zone="command"] { --zs: var(--z-command-2); }
.doc .zone[data-zone="warning"] { --zs: var(--z-warning-2); }
.doc .zone[data-zone="indorse"] { --zs: var(--z-indorse-2); }

/* ::after = the colour stripe at the left edge of EVERY zone, running its full
   height. Visible whenever the zone has its decoded paint (Decoded mode AND
   after a correct Assemble drop). Same in mobile. */
.doc .zone::after {
  content: ''; position: absolute;
  left: 6px; top: 8px; bottom: 8px;
  width: 5px; border-radius: 3px;
  background: var(--zs);
  opacity: 0;
  transition: opacity 220ms var(--soft);
  pointer-events: none;
}
/* ::before = the chip label (CROWN/PARTIES/etc.) anchored to the top edge of
   each zone (in the 34-px header band reserved by padding-top), attached to
   the stripe. White text on the zone-accent colour. */
.doc .zone::before {
  content: attr(data-label);
  position: absolute;
  left: 14px; top: 8px;
  font: 800 0.56rem var(--font-mono); letter-spacing: 0.14em;
  color: #fff;
  padding: 3px 9px;
  border-radius: 4px;
  background: var(--zs);
  opacity: 0;
  transition: opacity 240ms var(--soft);
  white-space: nowrap; pointer-events: none;
  box-shadow: 0 3px 6px -3px rgba(0,0,0,0.35);
  z-index: 2;
}

/* DECODED mode — zones tinted, labels visible */
.widget[data-mode="decoded"] .doc .zone[data-zone="crown"]   { background: var(--z-crown);   }
.widget[data-mode="decoded"] .doc .zone[data-zone="parties"] { background: var(--z-parties); }
.widget[data-mode="decoded"] .doc .zone[data-zone="address"] { background: var(--z-address); }
.widget[data-mode="decoded"] .doc .zone[data-zone="recital"] { background: var(--z-recital); }
.widget[data-mode="decoded"] .doc .zone[data-zone="command"] { background: var(--z-command); }
.widget[data-mode="decoded"] .doc .zone[data-zone="warning"] { background: var(--z-warning); }
.widget[data-mode="decoded"] .doc .zone[data-zone="indorse"] { background: var(--z-indorse); }

/* Stripe + chip visible whenever the zone is paid (Decoded mode OR
   after a correct drop in Assemble). Both colour cues come along. */
.widget[data-mode="decoded"] .doc .zone::before,
.widget[data-mode="decoded"] .doc .zone::after { opacity: 1; }

.widget[data-mode="decoded"] .doc .zone:hover,
.widget[data-mode="decoded"] .doc .zone.is-active {
  box-shadow: inset 0 0 0 2px var(--zs), 0 10px 22px -14px rgba(0,0,0,0.35);
  transform: translateY(-1px);
}
.widget[data-mode="decoded"] .doc .zone[data-zone="crown"].is-active   { color: var(--z-crown-2);   }
.widget[data-mode="decoded"] .doc .zone[data-zone="parties"].is-active { color: var(--z-parties-2); }
.widget[data-mode="decoded"] .doc .zone[data-zone="address"].is-active { color: var(--z-address-2); }
.widget[data-mode="decoded"] .doc .zone[data-zone="recital"].is-active { color: var(--z-recital-2); }
.widget[data-mode="decoded"] .doc .zone[data-zone="command"].is-active { color: var(--z-command-2); }
.widget[data-mode="decoded"] .doc .zone[data-zone="warning"].is-active { color: var(--z-warning-2); }
.widget[data-mode="decoded"] .doc .zone[data-zone="indorse"].is-active { color: var(--z-indorse-2); }

/* RAW mode — pristine document with a subtle "FILED" stamp */
.widget[data-mode="raw"] .doc .zone { cursor: text; }
.widget[data-mode="raw"] .doc::after {
  content: 'FILED'; position: absolute; right: 32px; bottom: 36px;
  font: 900 1.6rem var(--font-mono); letter-spacing: 0.32em;
  color: rgba(154, 42, 42, 0.18);
  border: 3px solid rgba(154, 42, 42, 0.18); border-radius: 6px;
  padding: 8px 18px; transform: rotate(-8deg);
  pointer-events: none;
}

/* ---------- ASSEMBLE mode — blank zones + drag tray ---------- */
/* Blank assemble zones show ONLY the centred "drop X here" prompt. The real
   content is REMOVED from layout (not merely faded) when the zone is empty —
   otherwise it sits as a wide flex sibling that shoves a long prompt
   ("DROP PETITIONER & RESPONDENTS HERE") past the zone's, and the document's,
   left margin (Papa 2026-06-07, phone bug). The filled (.is-correct) zone
   restores the content via the rules further down. */
.widget[data-mode="assemble"] .doc .zone:not(.is-correct) .zone-content { display: none; }
.widget[data-mode="assemble"] .doc .zone {
  background: transparent;
  border: 2px dashed rgba(120,90,40,0.22);
  border-radius: 8px;
  min-height: 76px;
  margin: 10px -10px;
  padding: 12px 14px;
  cursor: default;
  display: flex; align-items: center; justify-content: center;
}
.widget[data-mode="assemble"] .doc .zone .slot-prompt {
  font: 700 0.74rem var(--font-mono); letter-spacing: 0.18em;
  color: rgba(120,90,40,0.45);
  text-transform: uppercase;
  /* Wrap + centre + stay inside the zone so a long label can never spill past
     the left margin (Papa 2026-06-07, phone bug). */
  text-align: center; white-space: normal; overflow-wrap: anywhere;
  max-width: 100%; line-height: 1.5;
}
/* Live drag feedback — green ring if pointer is over the correct zone, red ring if wrong */
.widget[data-mode="assemble"] .doc .zone.is-drag-over-correct {
  background: rgba(91,122,29,0.18);
  border-color: var(--success, #5b7a1d);
  border-style: solid;
  box-shadow:
    inset 0 0 0 2px var(--success, #5b7a1d),
    0 0 32px -4px rgba(91,122,29,0.55);
  transform: scale(1.015);
}
.widget[data-mode="assemble"] .doc .zone.is-drag-over-wrong {
  background: rgba(194,64,42,0.14);
  border-color: var(--danger, #c2402a);
  border-style: solid;
  box-shadow:
    inset 0 0 0 2px var(--danger, #c2402a),
    0 0 32px -4px rgba(194,64,42,0.55);
  animation: wrongPulse 0.6s ease-in-out infinite;
}
@keyframes wrongPulse {
  0%, 100% { box-shadow: inset 0 0 0 2px var(--danger, #c2402a), 0 0 24px -4px rgba(194,64,42,0.55); }
  50%      { box-shadow: inset 0 0 0 2px var(--danger, #c2402a), 0 0 40px -2px rgba(194,64,42,0.75); }
}
/* When a zone locks in correctly, restore the EXACT Decoded look:
   the colour fill, the label tab in the margin, the same padding/margin/
   radius geometry, and the left-rule `::after` cue. The user's eye should
   see the zone become identical to its Decoded twin — that's the reward. */
.widget[data-mode="assemble"] .doc .zone.is-correct {
  border: 0;
  min-height: auto;
  /* Match the same geometry as Decoded zones so a filled Assemble zone is
     visually identical to its Decoded twin, including header room for the chip. */
  padding: 34px 16px 14px 28px;
  margin: 10px -14px;
  border-radius: 6px;
  background: var(--zone-bg, transparent);
  display: block;
  cursor: default;
  animation: snapIn 700ms var(--spring);
}
/* Filled Assemble zones get the same stripe + chip as Decoded zones. */
.widget[data-mode="assemble"] .doc .zone.is-correct::before,
.widget[data-mode="assemble"] .doc .zone.is-correct::after { opacity: 1; }
.widget[data-mode="assemble"] .doc .zone.is-correct .zone-content { opacity: 1; transition: opacity 400ms var(--soft) 200ms; }
.widget[data-mode="assemble"] .doc .zone.is-correct .slot-prompt { display: none; }
.widget[data-mode="assemble"] .doc .zone[data-zone="crown"].is-correct   { --zone-bg: var(--z-crown);   }
.widget[data-mode="assemble"] .doc .zone[data-zone="parties"].is-correct { --zone-bg: var(--z-parties); }
.widget[data-mode="assemble"] .doc .zone[data-zone="address"].is-correct { --zone-bg: var(--z-address); }
.widget[data-mode="assemble"] .doc .zone[data-zone="recital"].is-correct { --zone-bg: var(--z-recital); }
.widget[data-mode="assemble"] .doc .zone[data-zone="command"].is-correct { --zone-bg: var(--z-command); }
.widget[data-mode="assemble"] .doc .zone[data-zone="warning"].is-correct { --zone-bg: var(--z-warning); }
.widget[data-mode="assemble"] .doc .zone[data-zone="indorse"].is-correct { --zone-bg: var(--z-indorse); }

@keyframes snapIn {
  0%   { transform: scale(0.90); box-shadow: 0 0 0 0  rgba(91,122,29,0.0); }
  22%  { transform: scale(1.12); box-shadow: 0 0 0 20px rgba(91,122,29,0.55); }
  55%  { transform: scale(0.97); box-shadow: 0 0 0 8px  rgba(91,122,29,0.25); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0  rgba(91,122,29,0.0); }
}

/* Burst ripple at the zone centre when a tile lands correctly */
.burst {
  position: fixed; pointer-events: none; z-index: 10000;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent);
  animation: burstExpand 620ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  mix-blend-mode: multiply;
}
@keyframes burstExpand {
  0%   { transform: translate(-50%, -50%) scale(0.4); opacity: 0.95; }
  55%  { opacity: 0.45; }
  100% { transform: translate(-50%, -50%) scale(18);  opacity: 0; }
}

/* Progress dot pop — satisfying scale punch when the dot turns green */
.assemble-tray .pd.is-done {
  background: var(--success, #5b7a1d);
  border-color: var(--success, #5b7a1d);
  animation: dotPop 520ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
@keyframes dotPop {
  0%   { transform: scale(0.6); }
  55%  { transform: scale(1.55); }
  100% { transform: scale(1.15); }
}

/* Assemble tray — pinned to the viewport bottom so tiles are ALWAYS reachable
   while the writ scrolls above. Uses position:fixed (more reliable than
   sticky inside the sticky .doc-stage). Body gets extra bottom padding in
   Assemble mode so the writ's last lines never hide behind the tray. */
.assemble-tray {
  display: none;
  margin-top: 18px; padding: 14px 16px;
  /* Fully opaque — writ behind must NOT show through. backdrop-filter
     removed: it was creating a new containing block for fixed descendants
     in Chrome, throwing dragged tiles off-screen. */
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  border-top: 2px solid var(--accent);
  border-radius: 14px;
  box-shadow: 0 -20px 44px -16px rgba(0,0,0,0.55), 0 -4px 8px -2px rgba(0,0,0,0.18);
}
.widget[data-mode="assemble"] .assemble-tray {
  /* Bounded flex column: head pinned top, result/buttons pinned bottom (always
     visible), the tile list scrolls in between. Without the max-height the fixed
     tray grew past the screen and the success panel beneath the tiles fell off
     the bottom with no way to scroll to it (Papa 2026-06-07). dvh handles the
     mobile browser UI; vh is the fallback for older engines. */
  display: flex; flex-direction: column;
  max-height: calc(100vh - 28px);
  max-height: calc(100dvh - 28px);
  position: fixed;
  left: 16px; right: 16px; bottom: 14px;
  /* z-index pushed well above the decoder pane and any sticky ancestors. The
   * decoder column had a stacking context (transform on .is-active cards)
   * that was rendering its cards over the previous z-index:40 tray on the
   * right edge of the viewport. 9999 + will-change:transform (forces own
   * compositor layer) guarantees nothing in the page renders on top. */
  z-index: 9999;
  will-change: transform;
  margin: 0; max-width: 1180px;
  margin-left: auto; margin-right: auto;
  background-color: var(--bg-elev);
  opacity: 1;
  isolation: isolate;
  animation: trayRise 380ms var(--spring) forwards;
}
@media (max-width: 560px) {
  .widget[data-mode="assemble"] .assemble-tray { left: 8px; right: 8px; bottom: 8px; padding: 12px; max-height: calc(100vh - 16px); max-height: calc(100dvh - 16px); }
  /* Phone: shrink the draggable chips + the drop-prompt so long labels wrap
     tidily and more tiles fit without overflowing the tray (Papa 2026-06-07). */
  .tile { padding: 8px 12px; font-size: 0.68rem; letter-spacing: 0.06em; gap: 6px; }
  .widget[data-mode="assemble"] .doc .zone .slot-prompt { font-size: 0.66rem; letter-spacing: 0.08em; }
  /* Stack the result message + buttons cleanly (full-width) instead of a
     space-between wrap that scattered them. */
  .assemble-result.is-shown { flex-direction: column; align-items: stretch; gap: 10px; }
  .assemble-result.is-shown > span { margin-right: 0; text-align: center; }
  .assemble-result button { width: 100%; }
}
/* Reserve room at the bottom so sticky tray doesn't cover the writ's footer */
body.has-assemble-tray { padding-bottom: 220px; }
@keyframes trayRise {
  from { transform: translateY(120%); }
  to   { transform: translateY(0); }
}
.assemble-tray .tray-head {
  position: relative;
  display: flex; flex-direction: column; align-items: flex-start;
  margin-bottom: 12px; gap: 10px;
  /* Reserve the top-right corner for the close (X) — the normal close-button
     spot — so the heading wraps onto the next line instead of shoving the X down. */
  padding-right: 44px;
}
.assemble-tray .tray-head h3 {
  display: flex; align-items: center; gap: 8px;
  font: 800 0.86rem var(--font-mono); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink);
}
.assemble-tray .tray-head h3 svg { width: 18px; height: 18px; color: var(--accent); }
.assemble-tray .tray-head .tray-sub {
  font: 500 0.78rem var(--font-body); color: var(--ink-muted); letter-spacing: 0;
}
.assemble-tray .tray-head-right { display: flex; align-items: center; gap: 14px; }
.assemble-tray .progress-dots { display: flex; gap: 6px; }
.assemble-tray .tray-close {
  position: absolute; top: 0; right: 0;
  flex: 0 0 auto;
  display: inline-grid; place-items: center;
  width: 32px; height: 32px; padding: 0;
  border-radius: 9px; cursor: pointer;
  color: var(--ink-muted);
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  transition: color 160ms var(--soft), background 160ms var(--soft), border-color 160ms var(--soft), transform 120ms var(--spring);
}
.assemble-tray .tray-close svg { width: 18px; height: 18px; }
.assemble-tray .tray-close:hover {
  color: var(--ink);
  border-color: color-mix(in srgb, var(--danger) 55%, var(--hairline-2));
  background: color-mix(in srgb, var(--danger) 12%, var(--bg-elev));
}
.assemble-tray .tray-close:active { transform: scale(0.92); }
.assemble-tray .pd {
  width: 10px; height: 10px; border-radius: 50%;
  border: 2px solid var(--hairline-2); background: transparent;
  transition: background 240ms var(--spring), border-color 240ms var(--soft), transform 240ms var(--spring);
}
/* .pd.is-done rule lives below — uses dotPop animation for the satisfying pop */
/* Head + result stay put; only the tile list scrolls — so the success panel's
   buttons are always reachable at the bottom of the tray (Papa 2026-06-07). */
.assemble-tray .tray-head, .assemble-tray .assemble-result { flex: 0 0 auto; }
.assemble-tray .tray-tiles {
  display: flex; flex-wrap: wrap; gap: 10px;
  /* Takes the space left between the pinned head and result, and scrolls INSIDE
     the tray (not the page); overscroll-behavior:contain stops the scroll
     chaining to the document behind it. Dragged tiles are reparented to <body>
     with position:fixed, so this overflow never clips a tile mid-drag. */
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.tile {
  cursor: grab;
  user-select: none; -webkit-user-select: none; touch-action: none;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 16px; border-radius: 10px;
  font: 800 0.78rem var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase;
  background: var(--bg); border: 1px solid var(--hairline-2);
  box-shadow: 0 6px 12px -8px rgba(0,0,0,0.25), inset 0 -2px 0 rgba(0,0,0,0.05);
  transition: box-shadow 200ms var(--soft);
  /* Long labels wrap inside the chip rather than stretching it past the tray
     width (Papa 2026-06-07, phone bug). */
  white-space: normal; text-align: center; max-width: 100%; line-height: 1.3;
}
.tile:hover { box-shadow: 0 12px 24px -12px rgba(0,0,0,0.35); }
.tile.is-dragging {
  cursor: grabbing;
  /* tilt only — no scale. transform-origin pinned to top-left so the
     rotation pivots at the cursor's anchor point (we measure offX/offY from
     top-left in JS), preventing any visual drift between tile and cursor. */
  transform: rotate(-2.5deg);
  transform-origin: 0 0;
  box-shadow: 0 24px 40px -16px rgba(0,0,0,0.55), 0 0 0 2px rgba(184,99,42,0.45);
  z-index: 100;
  transition: none;
  will-change: left, top;
}
.tile.is-placed { opacity: 0.25; pointer-events: none; }
.tile.is-shake { animation: shake 360ms ease-in-out; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-8px); }
  75% { transform: translateX(8px); }
}
.tile[data-zone="crown"]   { color: var(--z-crown-2);   border-color: var(--z-crown-2);   background: linear-gradient(180deg, #fff, var(--z-crown));   }
.tile[data-zone="parties"] { color: var(--z-parties-2); border-color: var(--z-parties-2); background: linear-gradient(180deg, #fff, var(--z-parties)); }
.tile[data-zone="address"] { color: var(--z-address-2); border-color: var(--z-address-2); background: linear-gradient(180deg, #fff, var(--z-address)); }
.tile[data-zone="recital"] { color: var(--z-recital-2); border-color: var(--z-recital-2); background: linear-gradient(180deg, #fff, var(--z-recital)); }
.tile[data-zone="command"] { color: var(--z-command-2); border-color: var(--z-command-2); background: linear-gradient(180deg, #fff, var(--z-command)); }
.tile[data-zone="warning"] { color: var(--z-warning-2); border-color: var(--z-warning-2); background: linear-gradient(180deg, #fff, var(--z-warning)); }
.tile[data-zone="indorse"] { color: var(--z-indorse-2); border-color: var(--z-indorse-2); background: linear-gradient(180deg, #fff, var(--z-indorse)); }

.assemble-result {
  display: none;
  margin-top: 14px; padding: 14px 16px;
  background: linear-gradient(90deg, rgba(91,122,29,0.12), transparent);
  border: 1px solid rgba(91,122,29,0.35);
  border-radius: 10px;
  font-family: var(--font-display); font-style: italic;
}
/* message hugs the left (margin-right:auto), the two buttons sit together on the
   right — instead of space-between scattering "Try again" to the centre
   (Papa 2026-06-07). Mobile stacks them (media query below). */
.assemble-result.is-shown { display: flex; justify-content: flex-end; align-items: center; gap: 10px; flex-wrap: wrap; animation: fadeRise 500ms var(--spring); }
.assemble-result.is-shown > span { margin-right: auto; }
.assemble-result button {
  appearance: none; cursor: pointer;
  background: var(--ink); color: var(--cta-ink); border: 0;
  padding: 9px 16px; border-radius: 8px;
  font: 700 0.72rem var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase;
}
@keyframes fadeRise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- DECODED-MODE CALL-TO-ACTION (persistent, dismissible) ---------- */
.decoded-cta {
  display: none;
  align-items: center; gap: 12px;
  padding: 12px 14px; margin: 0 0 14px;
  background: linear-gradient(90deg, rgba(184,99,42,0.14), rgba(184,99,42,0.04));
  border: 1px solid rgba(184,99,42,0.30);
  border-radius: 12px;
  font-size: 0.92rem; color: var(--ink);
  animation: fadeRise 380ms var(--spring);
}
/* Show CTA on mobile (always) and on desktop ONLY when in focus mode (decoder hidden).
   On desktop split mode the decoder is already visible — no banner needed. */
@media (max-width: 980px) {
  .widget[data-mode="decoded"]:not(.cta-dismissed) .decoded-cta { display: flex; }
}
@media (min-width: 981px) {
  .widget[data-mode="decoded"][data-pane="focus"]:not(.cta-dismissed) .decoded-cta { display: flex; }
}
.decoded-cta .cta-ico {
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--accent); color: var(--cta-ink);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  animation: ctaTap 1.8s ease-in-out infinite;
}
.decoded-cta .cta-ico svg { width: 18px; height: 18px; }
@keyframes ctaTap {
  0%, 100% { transform: scale(1); }
  35%      { transform: scale(1.12); }
  70%      { transform: scale(0.96); }
}
.decoded-cta .cta-text { line-height: 1.45; }
.decoded-cta .cta-text b { color: var(--accent); }
.decoded-cta .cta-dismiss {
  margin-left: auto; appearance: none; background: transparent; border: 0;
  color: var(--ink-muted); cursor: pointer; font-size: 22px; line-height: 1;
  padding: 4px 10px; border-radius: 6px; flex-shrink: 0;
}
.decoded-cta .cta-dismiss:hover { color: var(--ink); background: rgba(0,0,0,0.06); }

/* ---------- TAP HINT (Decoded mode, first visit) ---------- */
.tap-hint {
  display: none;
  position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
  z-index: 6; pointer-events: none;
}
.widget[data-mode="decoded"]:not(.hint-dismissed) .doc .zone[data-zone="crown"] .tap-hint { display: block; }
.tap-hint .pulse-dot {
  position: relative; width: 14px; height: 14px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 var(--accent);
  animation: tapPulse 1.6s ease-out infinite;
}
.tap-hint .pulse-label {
  position: absolute; left: -86px; top: 50%; transform: translateY(-50%);
  background: var(--ink); color: var(--cta-ink);
  font: 800 0.66rem var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase;
  padding: 6px 10px; border-radius: 6px; white-space: nowrap;
}
.tap-hint .pulse-label::after {
  content: ''; position: absolute; right: -5px; top: 50%; transform: translateY(-50%) rotate(45deg);
  width: 10px; height: 10px; background: var(--ink);
}
@keyframes tapPulse {
  0%   { box-shadow: 0 0 0 0 rgba(184,99,42,0.55); }
  70%  { box-shadow: 0 0 0 16px rgba(184,99,42,0); }
  100% { box-shadow: 0 0 0 0 rgba(184,99,42,0); }
}
@media (max-width: 760px) {
  .tap-hint { left: auto; right: 8px; top: 8px; transform: none; }
  .tap-hint .pulse-label { left: auto; right: 24px; }
  .tap-hint .pulse-label::after { left: -5px; right: auto; }
}

/* ---------- PHRASE TOOLTIPS (key exam terms inside the writ) ---------- */
.doc .hint {
  text-decoration: underline dotted rgba(184,99,42,0.6) 1.5px;
  text-underline-offset: 4px;
  cursor: help;
  position: relative;
  transition: background 200ms var(--soft);
  border-radius: 3px;
  padding: 0 2px;
}
.doc .hint:hover, .doc .hint.is-tipped {
  background: rgba(184,99,42,0.10);
}
.doc .hint::after {
  content: attr(data-tip);
  position: absolute; bottom: calc(100% + 10px); left: 50%; transform: translateX(-50%) translateY(4px);
  background: #1a1410; color: #fbf6ec;
  padding: 10px 13px; border-radius: 10px;
  font: 500 0.78rem var(--font-body);
  font-style: normal; line-height: 1.5;
  width: max-content; max-width: 280px;
  z-index: 30; pointer-events: none;
  opacity: 0; visibility: hidden;
  transition: opacity 200ms var(--soft), transform 200ms var(--soft), visibility 0s linear 200ms;
  box-shadow: 0 16px 28px -12px rgba(0,0,0,0.55);
}
.doc .hint::before {
  content: ''; position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 6px solid transparent; border-right: 6px solid transparent;
  border-top: 6px solid #1a1410;
  z-index: 30; pointer-events: none;
  opacity: 0; transition: opacity 200ms var(--soft);
}
.doc .hint:hover::after, .doc .hint.is-tipped::after {
  opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0);
  transition: opacity 200ms var(--soft), transform 200ms var(--soft);
}
.doc .hint:hover::before, .doc .hint.is-tipped::before { opacity: 1; }

/* ---------- CONFETTI on Assemble win ---------- */
.confetti {
  position: fixed; top: -20px;
  width: 10px; height: 14px; z-index: 10001; pointer-events: none;
  animation: confettiFall 2s cubic-bezier(.45,.05,.55,.95) forwards;
}
@keyframes confettiFall {
  0%   { transform: translateY(0) rotate(0); opacity: 1; }
  100% { transform: translateY(110vh) rotate(720deg); opacity: 0.85; }
}

/* ---------- The writ's typographic chrome ---------- */
.doc .coat { display: block; margin: 0 auto 6px; }
.doc h1.title {
  font-family: 'Times New Roman', serif;
  text-align: center; font-weight: 700; font-size: 1.6rem; letter-spacing: 0.04em;
  text-transform: uppercase; margin: 4px 0 2px;
}
.doc .order-ref { text-align: center; font-style: italic; font-size: 0.92rem; margin-bottom: 14px; }
.doc .suit-line { font-size: 0.9rem; margin: 8px 0 10px; line-height: 1.55; }
.doc .suit-line .dots { letter-spacing: 0.25em; color: #886b48; }
.doc h2.court { text-align: center; font-weight: 700; font-size: 1.05rem; line-height: 1.5; margin: 14px 0 6px; }
.doc .division { text-align: center; font-style: italic; font-size: 0.92rem; line-height: 1.5; margin: 0 0 14px; }

.doc .between { text-align: center; font-weight: 700; letter-spacing: 0.08em; margin: 8px 0 4px; }
.doc .party-row {
  display: grid; grid-template-columns: 1fr auto; gap: 18px;
  margin: 6px 0; align-items: start;
}
.doc .party-row .who { font-weight: 700; text-transform: uppercase; }
.doc .party-row .addr { font-size: 0.9rem; color: #2a221a; }
.doc .party-row .role { font-weight: 700; align-self: end; font-style: italic; }
.doc .and-sep { text-align: center; font-weight: 700; margin: 6px 0; }

.doc .to-line { margin: 12px 0 8px; }
.doc p.body { margin: 10px 0; }
.doc p.body strong.cap { font-weight: 700; }

.doc .filing-note { font-style: italic; font-size: 0.82rem; color: #6a594a; margin: 12px 0 8px; text-align: center; }
.doc .dated { margin: 14px 0 4px; letter-spacing: 0.05em; }
.doc .dated .dots { letter-spacing: 0.25em; color: #886b48; }
.doc .cj { font-weight: 700; }
.doc .nb { font-style: italic; font-size: 0.78rem; color: #4a3f33; margin-top: 12px; padding-top: 10px; border-top: 1px dashed rgba(120,90,40,0.25); }

/* Affidavit averment lists (the numbered sworn paragraphs). The data files set an
   inline padding-left:24px gutter, which is fine at the precedent font but too narrow
   for a two-digit marker ("10.") at the large study-page reading font — the outside
   marker overflows its gutter and collides with the paragraph text (Papa, 2026-06-14,
   "10 is overlapping" on the transfer affidavit). An em-based gutter scales with the
   font so single- and double-digit numbers always clear; !important beats the inline
   px value. App-wide: every affidavit doc across all courses uses .averments. */
.doc .averments { padding-left: 2.4em !important; list-style-position: outside; }
.doc .averments > li { padding-left: 0.3em; }

/* ---------- DECODER PANE (desktop) ----------
   Cards flow naturally as a flex column. The matchHeights() JS pass sets each
   pair (zone + card) to the same min-height (= max of the two natural heights),
   so the writ and decoder columns advance in lockstep and never overlap. The
   decoder pane also gets a padding-top equal to the writ's pre-first-zone
   offset so the very first card lines up with the very first zone. */
.decoder {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;            /* matches the writ zones' inter-row gap */
  min-height: 600px;
}
.zone-card { position: relative; }
@media (max-width: 980px) { .decoder { display: none; } }

.zone-card {
  /* position is set above (absolute on desktop, static on mobile) so cards
     row-sync with their writ zones; do NOT override it here. */
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  border-radius: 14px; padding: 0;
  overflow: hidden;
  transition: box-shadow 250ms var(--soft), transform 250ms var(--spring);
  cursor: pointer;
}
.zone-card::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
}
.zone-card[data-zone="crown"]::before   { background: var(--z-crown-2);   }
.zone-card[data-zone="parties"]::before { background: var(--z-parties-2); }
.zone-card[data-zone="address"]::before { background: var(--z-address-2); }
.zone-card[data-zone="recital"]::before { background: var(--z-recital-2); }
.zone-card[data-zone="command"]::before { background: var(--z-command-2); }
.zone-card[data-zone="warning"]::before { background: var(--z-warning-2); }
.zone-card[data-zone="indorse"]::before { background: var(--z-indorse-2); }

.zone-card.is-active {
  transform: translateY(-2px) scale(1.015);
  box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5);
}
/* Active card — outline ring + soft tinted background fill. Two cues for one
   focus state. The outline is the zone's bold accent; the fill is the same
   pastel as the zone's tint in the writ, mixed at ~38% into the elev surface
   so text inside the card still reads cleanly. */
.zone-card[data-zone="crown"].is-active   { background: color-mix(in srgb, var(--z-crown)   38%, var(--bg-elev)); box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5), 0 0 0 2px var(--z-crown-2);   }
.zone-card[data-zone="parties"].is-active { background: color-mix(in srgb, var(--z-parties) 38%, var(--bg-elev)); box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5), 0 0 0 2px var(--z-parties-2); }
.zone-card[data-zone="address"].is-active { background: color-mix(in srgb, var(--z-address) 38%, var(--bg-elev)); box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5), 0 0 0 2px var(--z-address-2); }
.zone-card[data-zone="recital"].is-active { background: color-mix(in srgb, var(--z-recital) 38%, var(--bg-elev)); box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5), 0 0 0 2px var(--z-recital-2); }
.zone-card[data-zone="command"].is-active { background: color-mix(in srgb, var(--z-command) 38%, var(--bg-elev)); box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5), 0 0 0 2px var(--z-command-2); }
.zone-card[data-zone="warning"].is-active { background: color-mix(in srgb, var(--z-warning) 38%, var(--bg-elev)); box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5), 0 0 0 2px var(--z-warning-2); }
.zone-card[data-zone="indorse"].is-active { background: color-mix(in srgb, var(--z-indorse) 38%, var(--bg-elev)); box-shadow: 0 20px 36px -14px rgba(0,0,0,0.5), 0 0 0 2px var(--z-indorse-2); }
.widget.is-touring .zone-card[data-zone="crown"].is-active   { background: color-mix(in srgb, var(--z-crown)   45%, var(--bg-elev)); }
.widget.is-touring .zone-card[data-zone="parties"].is-active { background: color-mix(in srgb, var(--z-parties) 45%, var(--bg-elev)); }
.widget.is-touring .zone-card[data-zone="address"].is-active { background: color-mix(in srgb, var(--z-address) 45%, var(--bg-elev)); }
.widget.is-touring .zone-card[data-zone="recital"].is-active { background: color-mix(in srgb, var(--z-recital) 45%, var(--bg-elev)); }
.widget.is-touring .zone-card[data-zone="command"].is-active { background: color-mix(in srgb, var(--z-command) 45%, var(--bg-elev)); }
.widget.is-touring .zone-card[data-zone="warning"].is-active { background: color-mix(in srgb, var(--z-warning) 45%, var(--bg-elev)); }
.widget.is-touring .zone-card[data-zone="indorse"].is-active { background: color-mix(in srgb, var(--z-indorse) 45%, var(--bg-elev)); }
.zone-card .zc-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px 10px;
  background: linear-gradient(180deg, rgba(255,255,255,0.04), transparent);
}
.zone-card .zc-icon {
  width: 34px; height: 34px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
}
.zone-card[data-zone="crown"]   .zc-icon { background: var(--z-crown-2);   }
.zone-card[data-zone="parties"] .zc-icon { background: var(--z-parties-2); }
.zone-card[data-zone="address"] .zc-icon { background: var(--z-address-2); }
.zone-card[data-zone="recital"] .zc-icon { background: var(--z-recital-2); }
.zone-card[data-zone="command"] .zc-icon { background: var(--z-command-2); }
.zone-card[data-zone="warning"] .zc-icon { background: var(--z-warning-2); }
.zone-card[data-zone="indorse"] .zc-icon { background: var(--z-indorse-2); }
.zone-card .zc-icon svg { width: 18px; height: 18px; }
.zone-card .zc-num {
  font: 700 0.7rem var(--font-mono); letter-spacing: 0.1em;
  color: var(--ink-muted);
}
.zone-card .zc-label {
  font: 800 0.95rem var(--font-mono); letter-spacing: 0.14em;
  text-transform: uppercase; margin-left: auto;
}
.zone-card[data-zone="crown"]   .zc-label { color: var(--z-crown-2);   }
.zone-card[data-zone="parties"] .zc-label { color: var(--z-parties-2); }
.zone-card[data-zone="address"] .zc-label { color: var(--z-address-2); }
.zone-card[data-zone="recital"] .zc-label { color: var(--z-recital-2); }
.zone-card[data-zone="command"] .zc-label { color: var(--z-command-2); }
.zone-card[data-zone="warning"] .zc-label { color: var(--z-warning-2); }
.zone-card[data-zone="indorse"] .zc-label { color: var(--z-indorse-2); }

.zone-card .mnem {
  font-family: var(--font-display); font-style: italic;
  font-size: 1.05rem; line-height: 1.55;
  padding: 8px 18px 14px; color: var(--ink);
  border-bottom: 1px dashed var(--hairline-2);
}
.zone-card .clauses { display: flex; flex-direction: column; padding: 10px 14px 14px; gap: 8px; }
.zone-card .clause {
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 11px 13px; font-size: 0.92rem; line-height: 1.55;
}
.zone-card .clause b { color: var(--accent); }
.zone-card .gloss {
  font-size: 0.84rem; color: var(--ink-muted); margin-top: 4px;
  padding-top: 6px; border-top: 1px dashed var(--hairline);
}

/* ---------- MOBILE: bottom sheet (replaces stacked decoder) ---------- */
.sheet-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,0.45);
  opacity: 0; pointer-events: none;
  transition: opacity 260ms var(--soft);
  /* Above shared.js's floating-action cluster (z-index 960) and TTS bar
     (z-index 950) so they can never steal taps meant for the sheet's
     close/next/prev buttons. */
  z-index: 9998;
}
.sheet-backdrop.is-open { opacity: 1; pointer-events: auto; }

.sheet {
  position: fixed; left: 0; right: 0; bottom: 0;
  background: var(--bg-elev); color: var(--ink);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -24px 48px -16px rgba(0,0,0,0.45);
  transform: translateY(100%);
  transition: transform 380ms var(--spring);
  /* Sits ABOVE the floating-action cluster (shared.js, z-index 960) so the
     cluster's pen/feedback/collapse buttons can't intercept taps on the
     sheet's controls. Pairs with .sheet-backdrop at 9998. */
  z-index: 9999;
  max-height: 82vh; display: flex; flex-direction: column;
}
.sheet.is-open { transform: translateY(0); }
.sheet-handle {
  width: 44px; height: 5px; background: var(--hairline-2); border-radius: 3px;
  margin: 10px auto 4px;
}
.sheet-head {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px 10px;
  border-bottom: 1px solid var(--hairline);
}
/* Bulletproof every interactive button inside the sheet: explicit
   pointer-events, no tap-delay, lifted onto its own stacking context so
   sibling content can never intercept the click. */
.sheet button {
  pointer-events: auto !important;
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(184,99,42,0.25);
  position: relative; z-index: 2;
}
/* The SVG icon inside prev/next/stop is the topmost element at the button's
   centre on touch screens — it can absorb the press and the click never
   reaches the button's handler. Marking icons pointer-events:none routes
   every press straight to the button. */
.sheet button svg, .sheet button > * { pointer-events: none; }
.sheet-nav-btn {
  appearance: none; background: transparent; border: 1px solid var(--hairline-2);
  color: var(--ink); width: 44px; height: 44px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  transition: background 180ms var(--soft); flex-shrink: 0;
}
.sheet-nav-btn:hover { background: var(--bg-sunk); }
.sheet-nav-btn:disabled { opacity: 0.3; cursor: not-allowed; }
.sheet-nav-btn svg { width: 20px; height: 20px; }
.sheet-head .spacer { flex: 1; }
.sheet-stop-btn {
  display: none;
  appearance: none; background: var(--danger, #c2402a); color: #fff;
  border: 0; border-radius: 999px; cursor: pointer;
  padding: 8px 14px;
  font: 800 0.72rem var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase;
  align-items: center; gap: 6px; flex-shrink: 0;
  animation: ttsPulse 1.4s ease-in-out infinite;
}
.sheet-stop-btn svg { width: 12px; height: 12px; }
.sheet.is-preview .sheet-stop-btn { display: inline-flex; }
.sheet-pause-btn {
  display: none;
  appearance: none; background: var(--bg-elev); color: var(--ink);
  border: 1px solid var(--hairline-2); border-radius: 999px; cursor: pointer;
  padding: 8px 14px;
  font: 800 0.72rem var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase;
  align-items: center; gap: 6px; flex-shrink: 0;
  transition: background 160ms var(--soft), border-color 160ms var(--soft);
}
.sheet-pause-btn svg { width: 13px; height: 13px; }
.sheet-pause-btn:hover { background: var(--bg-sunk); border-color: var(--accent); }
.sheet.is-preview .sheet-pause-btn { display: inline-flex; }
/* During the tour, hide the manual prev/next arrows. Two controllers (the
   timer + the user) fighting for the same sheet was the source of the
   "next mixes things up + TTS overlaps" bug. To navigate manually, the
   student stops the tour first. */
.sheet.is-preview .sheet-nav-btn { display: none; }
.sheet-close {
  appearance: none; background: var(--ink); border: 0;
  border-radius: 50%; color: var(--cta-ink); cursor: pointer;
  width: 48px; height: 48px;
  font-size: 26px; line-height: 1; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 180ms var(--soft), transform 160ms var(--spring);
  box-shadow: 0 6px 14px -6px rgba(0,0,0,0.45);
}
.sheet-close:hover { background: var(--accent); transform: scale(1.05); }
.sheet-close:active { transform: scale(0.95); }

/* ---------- SHEET CONTENT (preview LEFT, all text RIGHT) ---------- */
.sheet-content {
  display: grid;
  grid-template-columns: minmax(260px, 360px) 1fr;
  gap: 22px; align-items: start;
  padding: 18px 22px 24px;
  overflow-y: auto;
  max-height: calc(82vh - 80px);
  -webkit-overflow-scrolling: touch;
}
@media (max-width: 640px) {
  .sheet-content {
    grid-template-columns: 1fr;
    gap: 14px;
    padding: 14px 16px 18px;
  }
}
.sheet-textcol { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.sheet-meta { display: flex; flex-direction: column; gap: 4px; }

/* The "image" — a styled clone of the actual zone content from the writ,
   rendered with its decoded colour tint so the student sees the literal
   fragment of the writ this card is about. Far stronger than an icon. */
.sheet-zone-preview {
  padding: 14px 16px; border-radius: 14px;
  font-family: 'Times New Roman', Times, Georgia, serif;
  font-size: 12.5px; line-height: 1.5;
  color: var(--paper-ink);
  background: var(--paper-2);
  border: 1px solid var(--paper-edge);
  box-shadow: 0 10px 22px -10px rgba(0,0,0,0.3);
  overflow: hidden;
  max-height: 280px; overflow-y: auto;
}
.sheet-zone-preview[data-zone="crown"]   { background: var(--z-crown);   }
.sheet-zone-preview[data-zone="parties"] { background: var(--z-parties); }
.sheet-zone-preview[data-zone="address"] { background: var(--z-address); }
.sheet-zone-preview[data-zone="recital"] { background: var(--z-recital); }
.sheet-zone-preview[data-zone="command"] { background: var(--z-command); }
.sheet-zone-preview[data-zone="warning"] { background: var(--z-warning); }
.sheet-zone-preview[data-zone="indorse"] { background: var(--z-indorse); }

/* Constrain the writ-style typography inside the preview so it fits */
.sheet-zone-preview .coat { width: 44px; height: 44px; margin: 0 auto 4px; display: block; }
.sheet-zone-preview h1.title { font-size: 1rem; letter-spacing: 0.04em; margin: 2px 0 1px; text-align: center; font-weight: 700; text-transform: uppercase; }
.sheet-zone-preview .order-ref { font-size: 0.74rem; font-style: italic; text-align: center; margin-bottom: 6px; }
.sheet-zone-preview .suit-line { font-size: 0.74rem; }
.sheet-zone-preview h2.court { font-size: 0.84rem; text-align: center; font-weight: 700; margin-top: 4px; }
.sheet-zone-preview .division { font-size: 0.74rem; font-style: italic; text-align: center; }
.sheet-zone-preview .between, .sheet-zone-preview .and-sep { font-size: 0.78rem; font-weight: 700; text-align: center; letter-spacing: 0.06em; margin: 4px 0; }
.sheet-zone-preview .party-row { display: grid; grid-template-columns: 1fr auto; gap: 8px; margin: 3px 0; }
.sheet-zone-preview .party-row .who { font-weight: 700; text-transform: uppercase; font-size: 0.76rem; }
.sheet-zone-preview .party-row .addr { font-size: 0.7rem; }
.sheet-zone-preview .party-row .role { font-weight: 700; font-style: italic; font-size: 0.74rem; align-self: end; }
.sheet-zone-preview p.body { margin: 4px 0; font-size: 0.82rem; }
.sheet-zone-preview .to-line { margin: 2px 0; font-size: 0.86rem; }
.sheet-zone-preview .filing-note { font-size: 0.7rem; font-style: italic; text-align: center; margin: 6px 0 4px; }
.sheet-zone-preview .dated { font-size: 0.78rem; margin: 4px 0; }
.sheet-zone-preview .cj { font-weight: 700; font-size: 0.78rem; }
.sheet-zone-preview .nb { font-size: 0.68rem; font-style: italic; margin-top: 6px; padding-top: 4px; border-top: 1px dashed rgba(0,0,0,0.18); }
.sheet-zone-preview .dots { letter-spacing: 0.15em; color: #876b48; }
.sheet-zone-preview .hint { text-decoration: none; cursor: default; }
.sheet-meta { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sheet-meta .sm-num {
  font: 700 0.68rem var(--font-mono); color: var(--ink-muted); letter-spacing: 0.14em;
}
.sheet-meta .sm-name {
  font: 800 1.1rem var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase;
}
.sheet-meta .sm-mnem {
  font-family: var(--font-display); font-style: italic;
  font-size: 1rem; line-height: 1.5; color: var(--ink);
  margin-top: 4px;
}

.sheet-body { padding: 0; }
/* Hide the body during tour-preview — only the preview + mnemonic show */
.sheet.is-preview .sheet-body { display: none; }
/* On mobile (stacked layout) we also want the preview to NOT scroll-trap;
   let the sheet itself handle scrolling. */
@media (max-width: 640px) {
  .sheet-zone-preview { max-height: none; overflow: visible; }
}
.sheet-body .mnem {
  font-family: var(--font-display); font-style: italic;
  font-size: 1.1rem; line-height: 1.55; margin-bottom: 12px;
  padding: 12px 14px; background: var(--bg);
  border: 1px solid var(--hairline-2); border-left: 4px solid currentColor;
  border-radius: 10px;
}
.sheet-body .clauses { display: flex; flex-direction: column; gap: 10px; }
.sheet-body .clause {
  background: var(--bg); border: 1px solid var(--hairline);
  border-radius: 10px; padding: 12px 14px; font-size: 0.95rem; line-height: 1.55;
}
.sheet-body .clause b { color: var(--accent); }
.sheet-body .gloss {
  font-size: 0.88rem; color: var(--ink-muted); margin-top: 6px;
  padding-top: 6px; border-top: 1px dashed var(--hairline);
}

/* ---------- TOUR PREVIEW STATE (progressive disclosure) ----------
   While the tour is running, every decoder card and the bottom sheet show
   only the icon + label + mnemonic. The full clause breakdown stays hidden
   until the user manually clicks a zone (which ends the tour and renders
   the full content). Same DNA on desktop cards and mobile sheet. */
.widget.is-touring .zone-card .clauses,
.sheet.is-preview .clauses { display: none; }

.widget.is-touring .zone-card .mnem,
.sheet.is-preview .mnem { font-size: 1.12rem; padding-bottom: 18px; }

/* During tour, non-active cards dim back so the user's eye locks onto the
   current zone's card. The active card gets a coloured outer ring matching
   the zone's accent, a softer scale, and a deeper lift. */
.widget.is-touring .zone-card {
  opacity: 0.42;
  transform: scale(0.97);
  transition: opacity 320ms var(--soft), transform 320ms var(--soft), box-shadow 320ms var(--soft);
}
.widget.is-touring .zone-card.is-active {
  opacity: 1;
  transform: scale(1.02) translateY(-2px);
}
.widget.is-touring .zone-card[data-zone="crown"].is-active   { box-shadow: 0 22px 38px -16px rgba(0,0,0,0.45), 0 0 0 3px var(--z-crown-2),   0 0 36px -4px var(--z-crown-2);   }
.widget.is-touring .zone-card[data-zone="parties"].is-active { box-shadow: 0 22px 38px -16px rgba(0,0,0,0.45), 0 0 0 3px var(--z-parties-2), 0 0 36px -4px var(--z-parties-2); }
.widget.is-touring .zone-card[data-zone="address"].is-active { box-shadow: 0 22px 38px -16px rgba(0,0,0,0.45), 0 0 0 3px var(--z-address-2), 0 0 36px -4px var(--z-address-2); }
.widget.is-touring .zone-card[data-zone="recital"].is-active { box-shadow: 0 22px 38px -16px rgba(0,0,0,0.45), 0 0 0 3px var(--z-recital-2), 0 0 36px -4px var(--z-recital-2); }
.widget.is-touring .zone-card[data-zone="command"].is-active { box-shadow: 0 22px 38px -16px rgba(0,0,0,0.45), 0 0 0 3px var(--z-command-2), 0 0 36px -4px var(--z-command-2); }
.widget.is-touring .zone-card[data-zone="warning"].is-active { box-shadow: 0 22px 38px -16px rgba(0,0,0,0.45), 0 0 0 3px var(--z-warning-2), 0 0 36px -4px var(--z-warning-2); }
.widget.is-touring .zone-card[data-zone="indorse"].is-active { box-shadow: 0 22px 38px -16px rgba(0,0,0,0.45), 0 0 0 3px var(--z-indorse-2), 0 0 36px -4px var(--z-indorse-2); }

/* "Tap to dig deeper" cue, shown only in preview/tour state */
.preview-cue {
  display: none;
  margin: 4px 14px 14px;
  padding: 9px 12px;
  font: 600 0.78rem var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent);
  background: rgba(184,99,42,0.08);
  border: 1px dashed rgba(184,99,42,0.35);
  border-radius: 8px;
  text-align: center;
}
.widget.is-touring .zone-card .preview-cue,
.sheet.is-preview .preview-cue { display: block; }

/* ---------- AUTO-TOUR PLAY BUTTON (next to mode toggle) ---------- */
.tour-btn {
  appearance: none; cursor: pointer;
  background: var(--ink); color: var(--cta-ink);
  border: 0; border-radius: 999px;
  padding: 7px 15px 7px 11px;
  font: 700 0.78rem var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 8px;
  transition: transform 200ms var(--soft), background 200ms var(--soft);
}
.tour-btn:hover { transform: translateY(-1px); }
.tour-btn svg { width: 14px; height: 14px; }
.tour-btn.is-running { background: var(--danger, #c2402a); }
.tour-btn.is-running .icon-play { display: none; }
.tour-btn:not(.is-running) .icon-stop { display: none; }
/* While the tour runs, the in-sheet Stop button is the primary control.
   We hide the toolbar tour button entirely so there's only one Stop in view. */
.tour-btn.is-hidden { display: none; }

/* Toolbar Pause/Resume — sits beside the tour Stop on desktop. Toggled via the
   `hidden` attribute (shown only while a tour is running with the decoder open). */
.tour-pause-btn {
  appearance: none; cursor: pointer;
  background: var(--bg-elev); color: var(--ink);
  border: 1px solid var(--hairline-2); border-radius: 999px;
  padding: 7px 14px 7px 11px;
  font: 700 0.78rem var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 7px;
  transition: transform 200ms var(--soft), background 200ms var(--soft), border-color 200ms var(--soft);
}
.tour-pause-btn[hidden] { display: none; }
.tour-pause-btn:hover { transform: translateY(-1px); border-color: var(--accent); }
.tour-pause-btn svg { width: 14px; height: 14px; }

.tour-progress {
  margin-left: 8px;
  font: 700 0.7rem var(--font-mono); color: var(--ink-muted); letter-spacing: 0.08em;
}
.tour-btn.is-running ~ .tour-progress { color: var(--accent); }

/* ---------- TTS SPEAKER BUTTON on decoder cards + sheet ----------
   Papa 2026-05-30: these are the WIDGET's per-zone speaker buttons. They reuse
   the ".tts-btn" class, which is ALSO the shared TTS bar's control-button class
   (shared.css). Because this sheet loads after shared.css on the drafting pages,
   the bare ".tts-btn" rules were bleeding onto the shared TTS bar — making its
   buttons 30px rounded-squares-with-a-border instead of the chapters' 38px
   circles ("the drafting TTS looks different"). SCOPED to #dw-app so they only
   style the widget's own buttons; the shared bar (injected outside #dw-app)
   reverts to its engine styling and now matches every chapter. */
#dw-app .tts-btn {
  appearance: none; cursor: pointer; flex-shrink: 0;
  background: transparent; border: 1px solid var(--hairline-2);
  color: var(--ink-muted);
  width: 30px; height: 30px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 180ms var(--soft), color 180ms var(--soft);
  margin-left: 8px;
}
#dw-app .tts-btn:hover { background: var(--bg-sunk); color: var(--ink); }
#dw-app .tts-btn svg { width: 15px; height: 15px; }
#dw-app .tts-btn.is-speaking { background: var(--accent); color: var(--cta-ink); border-color: var(--accent); animation: ttsPulse 1.2s ease-in-out infinite; }
@keyframes ttsPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(184,99,42,0.6); }
  50%      { box-shadow: 0 0 0 8px rgba(184,99,42,0); }
}

/* ---------- REDUCED MOTION ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .tap-hint .pulse-dot,
  .decoded-cta .cta-ico,
  .tts-btn.is-speaking { animation: none !important; }
  .confetti, .burst { display: none !important; }
}

/* ==================================================================
   DOCUMENT SWITCHER (go CV-DRAFT-NAV, 2026-05-29)
   Toolbar row (inside the sticky widget-bar) + in-flow footer pager.
   Lets a student move between drafting documents without returning to
   the Drafting tab. The footer pager is NOT fixed, so it never collides
   with the fixed bottom-right floating cluster.
   ================================================================== */
.dw-doc-switch {
  flex: 1 0 100%;                 /* wraps to its own row inside the sticky bar */
  display: flex; align-items: center; gap: 10px;
  /* No margin-top — the bar's 10px row-gap already separates this row from the
     controls above. Just a hairline divider + small breathing room below it so
     the switcher reads as part of the bar, not a detached floating card. */
  margin-top: 0; padding-top: 8px;
  border-top: 1px solid var(--hairline);
}
.dw-ds-arrow {
  flex: 0 0 auto; width: 38px; height: 38px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-elev); border: 1px solid var(--hairline-2); border-radius: 10px;
  color: var(--ink-muted); cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.dw-ds-arrow svg { width: 20px; height: 20px; }
.dw-ds-arrow:hover:not(:disabled) { background: var(--ink); color: var(--cta-ink); border-color: var(--ink); }
.dw-ds-arrow:disabled { opacity: .35; cursor: default; }
.dw-ds-center { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.dw-ds-kicker {
  font: 700 0.6rem var(--font-mono); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-muted);
}
.dw-ds-selwrap { position: relative; display: block; }
.dw-ds-select {
  -webkit-appearance: none; appearance: none;
  width: 100%; max-width: 100%; text-overflow: ellipsis;
  padding: 8px 34px 8px 12px;
  background: var(--bg-elev); border: 1px solid var(--hairline-2); border-radius: 10px;
  color: var(--ink); font: 700 0.9rem var(--font-display); cursor: pointer;
}
.dw-ds-select:hover { border-color: var(--accent); }
.dw-ds-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.dw-ds-caret {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; color: var(--ink-muted); pointer-events: none;
}

.dw-pager {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: stretch;
  max-width: 1080px; margin: 40px auto 30px; padding: 0 18px;
}
.dw-pager-link {
  display: flex; flex-direction: column; gap: 4px;
  padding: 14px 16px; border: 1px solid var(--hairline-2); border-radius: 12px;
  background: var(--bg-elev); color: inherit; text-decoration: none;
  transition: transform .15s, border-color .15s, box-shadow .15s;
}
.dw-pager-link.next { text-align: right; }
.dw-pager-link:hover:not(.is-disabled) { transform: translateY(-2px); border-color: var(--accent); }
.dw-pager-link.is-disabled { opacity: .4; pointer-events: none; }
.dw-pg-dir {
  display: inline-flex; align-items: center; gap: 5px;
  font: 700 0.62rem var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent);
}
.dw-pager-link.next .dw-pg-dir { justify-content: flex-end; }
.dw-pg-dir svg { width: 15px; height: 15px; }
.dw-pg-title { font: 600 0.96rem var(--font-display); color: var(--ink); }
.dw-pager-all {
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  padding: 14px 18px; border: 1px dashed var(--hairline-2); border-radius: 12px;
  background: transparent; color: var(--ink-muted); text-decoration: none;
  font: 700 0.62rem var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase;
  transition: color .15s, border-color .15s;
}
.dw-pager-all svg { width: 20px; height: 20px; }
.dw-pager-all:hover { color: var(--ink); border-color: var(--accent); }

@media (max-width: 640px) {
  .dw-pager { grid-template-columns: 1fr 1fr; margin-bottom: 96px; }
  .dw-pager-all { grid-column: 1 / -1; order: 3; flex-direction: row; }
}

