/* ─────────────────────────────────────────────────────────────────────────
   LinkedIn 4:5 Carousel Template
   Native canvas: 1080 × 1350 px
   Aesthetic: editorial-print, warm paper, ink, single rust accent
   ────────────────────────────────────────────────────────────────────────── */

:root {
  /* ── Slide canvas */
  --slide-w: 1080px;
  --slide-h: 1350px;

  /* ── Color tokens (paper theme — default) */
  --paper:   #F1ECE0;   /* warm cream, slightly desaturated */
  --paper-2: #E7E0D0;   /* secondary surface */
  --ink:     #1B1714;   /* warm near-black */
  --ink-2:   #4A433B;   /* secondary ink */
  --muted:   #675F56;   /* tertiary ink, marginalia — AA (>=4.5:1) on paper + paper-2 */
  --rule:    #C7BDAA;   /* hairline */
  --accent:  #B5462C;   /* signature warm rust */
  --accent-ink: #F1ECE0;

  /* ── Type scale (designed for 1080×1350 reading on a phone) */
  --t-hero:    112px;
  --t-display: 84px;
  --t-title:   64px;
  --t-h1:      52px;
  --t-h2:      40px;
  --t-lead:    34px;
  --t-body:    28px;
  --t-small:   22px;
  --t-mono:    18px;
  --t-tick:    14px;

  /* ── Spacing */
  --pad-x:   80px;
  --pad-y:   90px;
  --gap-xl:  72px;
  --gap-lg:  48px;
  --gap-md:  28px;
  --gap-sm:  14px;

  /* ── Lines */
  --hair: 1.5px;

  /* ── Font stacks */
  --f-display: "Instrument Serif", "Times New Roman", "Georgia", serif;
  --f-body:    "Geist", -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  --f-mono:    "JetBrains Mono", "SF Mono", "Menlo", "Consolas", monospace;

  /* ── Editor-shell layout (Phase 2 grid). The rail + tweaks tracks RESERVE
     the gutters so the centred stage can never underlap a fixed panel. The
     resizers in main.js overwrite --rail-w / --tweaks-w live, so the track
     width always equals the actual panel width. */
  --rail-w:   300px;   /* left Pages rail track (matches .edt) */
  --tweaks-w: 280px;   /* right Tweaks panel track (matches .twk-panel) */
  --shell-gap: 24px;   /* column gap between rail / stage / tweaks */
  --shell-pad: 16px;   /* outer inset (replaces the old fixed 16px panel insets) */

  /* ── Chrome surfaces (editor panels). Default = dark glass for the default
     warm-paper light theme so the chrome reads as a distinct tool layer over
     the page. Light/cream themes (paper/atea/studio/forest/tide) get a light
     glass; dark themes keep the dark glass — see the per-theme overrides. */
  --chrome-surface: rgba(20, 17, 14, 0.78);
  --chrome-ink:     #EFE9DB;
  --chrome-ink-dim: rgba(239, 233, 219, 0.7);
  --chrome-border:  rgba(255, 255, 255, 0.08);
  --chrome-line:    rgba(255, 255, 255, 0.06);
  --chrome-hover:   rgba(255, 255, 255, 0.08);
}

/* Ink theme override (applied via [data-theme="ink"]) */
[data-theme="ink"] {
  --paper:   #14110E;
  --paper-2: #1F1B17;
  --ink:     #EFE9DB;
  --ink-2:   #BFB6A5;
  --muted:   #8D846F;   /* AA on ink paper #14110E + paper-2 #1F1B17 (was #7A7264, 3.96:1) */
  --rule:    #3A332C;
  --accent-ink: #14110E;
}

/* Studio theme — Nordic blueprint: cool gray paper, deep navy ink,
   signature workmanlike blue. Architect's notebook, not magazine. */
[data-theme="studio"] {
  --paper:   #C5C9CC;
  --paper-2: #B6BBC0;
  --ink:     #0F1E2C;
  --ink-2:   #324657;
  --muted:   #444C53;   /* AA on studio paper #C5C9CC + paper-2 #B6BBC0 */
  --rule:    #8B949C;
  --accent:  #2A6F8F;
  --accent-ink: #C5C9CC;
}

/* Forest theme — dappled woodland: muted sage paper, deep forest ink,
   warm gold accent (the late-afternoon highlights). Picks up the
   bokeh palette of the photographer-y profile shot. */
[data-theme="forest"] {
  --paper:   #C9CFC0;
  --paper-2: #B5BCAB;
  --ink:     #1A241A;
  --ink-2:   #38453A;
  --muted:   #464C44;   /* AA on forest paper #C9CFC0 + paper-2 #B5BCAB */
  --rule:    #8B9587;
  --accent:  #B8862B;
  --accent-ink: #C9CFC0;
}

/* Grove theme — deep woodland: actual green paper with cream type and
   bronze accent. Feels like standing under the canopy rather than
   looking at a scan of paper that happens to be sage. */
[data-theme="grove"] {
  --paper:   #2A3526;
  --paper-2: #344029;
  --ink:     #E8E0CB;
  --ink-2:   #B5AE99;
  --muted:   #A3A98E;   /* AA on grove paper #2A3526 + paper-2 #344029 */
  --rule:    #4D5A43;
  --accent:  #D4A24C;
  --accent-ink: #2A3526;
}

/* Midnight — between ink and grove, pulled cool. Dark blue-charcoal
   with a hint of green, muted teal accent. Cooler, more technical mood. */
[data-theme="midnight"] {
  --paper:   #131A1F;
  --paper-2: #1B232A;
  --ink:     #DFE5E8;
  --ink-2:   #A8B0B6;
  --muted:   #838A92;   /* AA on midnight paper #131A1F + paper-2 #1B232A */
  --rule:    #2D3742;
  --accent:  #5BA098;
  --accent-ink: #131A1F;
}

/* Ember — between ink and grove, pulled warm. Smoky brown-charcoal
   with copper-amber accent. Hearth, ash, and warm wood. */
[data-theme="ember"] {
  --paper:   #1F1A14;
  --paper-2: #2A241B;
  --ink:     #EDE3CD;
  --ink-2:   #B8AB94;
  --muted:   #978A72;   /* AA on ember paper #1F1A14 + paper-2 #2A241B */
  --rule:    #3A322A;
  --accent:  #C97447;
  --accent-ink: #1F1A14;
}

/* Moss — the direct mid-point between ink and grove. Dark olive-moss
   paper, cream ink, golden-olive accent. Earthier than grove (less
   pure green, more sun-bleached). */
[data-theme="moss"] {
  --paper:   #232A1E;
  --paper-2: #2D352A;
  --ink:     #E5DEC4;
  --ink-2:   #B5AB8E;
  --muted:   #979E7A;   /* AA on moss paper #232A1E + paper-2 #2D352A */
  --rule:    #3F4736;
  --accent:  #C19944;
  --accent-ink: #232A1E;
}

/* Rose — masculine pink: deep wine-mauve paper, warm cream ink,
   dusty rose accent. Sophisticated, not Barbie. */
[data-theme="rose"] {
  --paper:   #3A2530;
  --paper-2: #45303A;
  --ink:     #F5E8E8;
  --ink-2:   #C9B5B5;
  --muted:   #B9969E;   /* AA on rose paper #3A2530 + paper-2 #45303A */
  --rule:    #5A3F49;
  --accent:  #DC8FA0;
  --accent-ink: #3A2530;
}

/* Plum — actual purple now, keyed on amethyst (#9966CC) per request.
   Deep saturated purple paper, cool cream ink. */
[data-theme="plum"] {
  --paper:   #221A33;
  --paper-2: #2C2440;
  --ink:     #E8E0F0;
  --ink-2:   #B0A8BD;
  --muted:   #948AAD;   /* AA on plum paper #221A33 + paper-2 #2C2440 */
  --rule:    #3F3550;
  --accent:  #9966CC;
  --accent-ink: #221A33;
}

/* Tide — light blue → dark blue. Designed to be used with the gradient
   tweak (right/left/alternate). The two paper tokens are the gradient
   stops, so any theme works with the gradient mode but tide is tuned
   for the maximum left-to-right shading effect. */
[data-theme="tide"] {
  --paper:   #5C7E9E;
  --paper-2: #1F2F47;
  --ink:     #F0E8D4;
  --ink-2:   #C5BEAC;
  /* Tide's --paper (#5C7E9E) is a mid-tone where even pure white tops out at
     ~4.26:1, so NO colour can reach AA 4.5:1 on the light stop (tide's own
     --ink only hits 3.49:1 — a theme-level constraint). We lighten --muted
     toward --ink so marginalia is as legible as the primary text on the light
     stop (3.45:1, up from 1.42:1) and well past AA on the dark paper-2 stop
     (10.9:1) used by the gradient's alternate slides. */
  --muted:   #EFE7D3;
  --rule:    #3D5673;
  --accent:  #E5B660;
  --accent-ink: #1F2F47;
}

/* ── Chrome surface, theme-linked ─────────────────────────────────────────
   The editor panels (.edt / .twk-panel docking frame / their inner surfaces)
   read these --chrome-* tokens. :root defines a DARK glass (the default warm
   light page still reads the chrome as a distinct dark tool layer). Light /
   cream-paper themes (paper/atea/studio/forest/tide) switch to a LIGHT glass
   built from their own --paper, so the chrome stops sitting as a heavy dark
   slab over a pale slide (finding chrome-vs-slide-language-clash-light-themes
   + hardcoded-chrome-colors-ignore-theme). Dark themes (ink/grove/midnight/
   ember/moss/rose/plum) keep the inherited dark glass — no override needed.
   NOTE: the Tweaks panel's own inner control colours are hardcoded in
   TWEAKS_STYLE (tweaks-panel.js, the Phase 5 vanilla panel); the rewrite
   preserved that cream-glass surface verbatim, so retinting the panel's inner
   controls remains intentionally out of scope. Here we theme-link the .edt rail
   + the panel's docking frame so the two panels stop clashing on light
   themes. */
[data-theme="paper"],
[data-theme="atea"],
[data-theme="studio"],
[data-theme="forest"],
[data-theme="tide"] {
  --chrome-surface: color-mix(in oklab, var(--paper) 82%, transparent);
  --chrome-ink:     var(--ink);
  --chrome-ink-dim: color-mix(in oklab, var(--ink) 70%, transparent);
  --chrome-border:  color-mix(in oklab, var(--ink) 12%, transparent);
  --chrome-line:    color-mix(in oklab, var(--ink) 9%, transparent);
  --chrome-hover:   color-mix(in oklab, var(--ink) 8%, transparent);
}

/* ── Gradient surface mode ────────────────────────────────────────────
   Toggle via body[data-gradient="right|left|alternate"]. When on, the
   slide background becomes a linear-gradient between --paper and
   --paper-2 (which every theme already defines). Works on any theme. */
body[data-gradient="right"] .slide {
  background:
    radial-gradient(ellipse 1200px 800px at 50% 0%, rgba(255,255,255,0.10), transparent 60%),
    linear-gradient(to right, var(--paper), var(--paper-2));
}
body[data-gradient="left"] .slide {
  background:
    radial-gradient(ellipse 1200px 800px at 50% 0%, rgba(255,255,255,0.10), transparent 60%),
    linear-gradient(to left, var(--paper), var(--paper-2));
}
body[data-gradient="alternate"] .slide {
  background:
    radial-gradient(ellipse 1200px 800px at 50% 0%, rgba(255,255,255,0.10), transparent 60%),
    linear-gradient(to right, var(--paper), var(--paper-2));
}
body[data-gradient="alternate"] .slide-cell:nth-child(even) .slide {
  background:
    radial-gradient(ellipse 1200px 800px at 50% 0%, rgba(255,255,255,0.10), transparent 60%),
    linear-gradient(to left, var(--paper), var(--paper-2));
}
/* full-bleed slide doesn't show a paper background — image covers it */
body[data-gradient] .slide--full { background: var(--paper); }

/* Atea theme — corporate brand variant. Inter typography (per Atea
   design system), clean white paper, brand green accent, cool grey ink. */
[data-theme="atea"] {
  --paper:   #FFFFFF;
  --paper-2: #F4F6F4;
  --ink:     #1F2937;
  --ink-2:   #4B5563;
  --muted:   #6C7079;   /* AA on atea paper #FFFFFF + paper-2 #F4F6F4 */
  --rule:    #E5E7EB;
  --accent:  #13AA52;
  --accent-ink: #FFFFFF;
  --f-display: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  --f-body:    "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
}
/* Atea uses bold sans for display, so override the italic-serif behavior.
   `.slide--cover h2` is listed alongside h1 so the demoted cover headline keeps
   the brand-bold look (templates.js renders the cover headline as <h2>). */
[data-theme="atea"] .slide--cover h1,
[data-theme="atea"] .slide--cover h2,
[data-theme="atea"] .slide--bullets h2,
[data-theme="atea"] .slide--steps h2,
[data-theme="atea"] .slide--imgtext h2,
[data-theme="atea"] .slide--close h2 {
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.0;
}
[data-theme="atea"] .slide--cover h1 em,
[data-theme="atea"] .slide--cover h2 em,
[data-theme="atea"] .slide--bullets h2 em,
[data-theme="atea"] .slide--steps h2 em,
[data-theme="atea"] .slide--imgtext h2 em,
[data-theme="atea"] .slide--close h2 em {
  font-style: normal;
  font-weight: 800;
  color: var(--accent);
}
[data-theme="atea"] .slide--quote blockquote {
  font-weight: 600;
  font-style: normal;
  letter-spacing: -0.02em;
}
[data-theme="atea"] .slide--quote .quote-mark {
  font-style: normal;
  font-weight: 800;
}
[data-theme="atea"] .slide--stat .stat-num {
  font-weight: 800;
  letter-spacing: -0.045em;
}
[data-theme="atea"] .slide--stat .stat-num em,
[data-theme="atea"] .slide--stat .stat-label {
  font-style: normal;
  font-weight: 600;
}
[data-theme="atea"] .steps .step__num {
  font-style: normal;
  font-weight: 800;
}

/* ── Shell ─────────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

/* ── Editor grid shell ────────────────────────────────────────────────────
   <body> is the grid container. It already holds, in DOM order, the left rail
   (aside.edt), the centred stage (div.app) and the Tweaks mount (#tweaks-root)
   — so three real tracks map onto them with no DOM reordering. The rail and
   tweaks tracks are fixed-width (var-driven), which RESERVES those gutters so
   the centred slide can never slide under either fixed/docked panel — the
   root cause of slide-under-tweaks-panel / tweaks-panel-covers-byline.
   (The <style>/<script> body children are display:none, so grid auto-placement
   skips them and they consume no tracks.) */
body {
  font-family: var(--f-body);
  background: #2A2622;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  display: grid;
  grid-template-columns:
    [rail]   var(--rail-w, 300px)
    [stage]  minmax(0, 1fr)
    [tweaks] var(--tweaks-w, 280px);
  grid-template-rows: auto;
  column-gap: var(--shell-gap, 24px);
  align-items: stretch;
  /* 100dvh (not 100vh) so a short single-slide deck still fills the viewport
     and the rail/panel columns reach full height, with mobile URL-bar
     correctness. Rows stay auto so a tall deck grows past the viewport and the
     page scrolls normally. */
  min-height: 100dvh;
  padding: var(--shell-pad, 16px);
}

.app {
  --preview-scale: 0.62;
  grid-column: stage;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 28px;
  padding: 48px 24px 120px;
}

.app__head {
  width: min(100%, 800px);
  color: #C9BFAB;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: 1px dashed #4A433B;
  padding-bottom: 14px;
}
.app__head b { color: #F1ECE0; font-weight: 500; letter-spacing: 0.04em; }
.app__head a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: rgba(241, 236, 224, 0.35);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color 120ms ease, text-decoration-color 120ms ease;
  cursor: pointer;
}
.app__head a:hover,
.app__head a:focus-visible {
  color: #F1ECE0;
  text-decoration-color: var(--accent, #B5462C);
}
.app__head a:focus-visible {
  outline: 2px solid var(--accent, #B5462C);
  outline-offset: 3px;
  border-radius: 2px;
}

.slides {
  display: flex;
  flex-direction: column;
  gap: 36px;
  align-items: center;
}

/* Each slide is rendered at native 1080x1350, then scaled into a smaller
   wrapper for screen preview. Print/PDF reverts to native size. */
.slide-cell {
  width: calc(var(--slide-w) * var(--preview-scale));
  height: calc(var(--slide-h) * var(--preview-scale));
  position: relative;
  box-shadow: 0 30px 60px rgba(0,0,0,0.35), 0 8px 18px rgba(0,0,0,0.25);
}
/* The slide-cell__num is a small "01 / 06" ruler label that floats to the
   LEFT of the cell. With the wider sidebar + bigger main slide it can read
   as overlapping the slide; it's also duplicative since every slide already
   prints `[ NN / NN ]` in its own chrome (via .serial). Hide everywhere by
   default — kept in the DOM so any custom CSS that wants it back can
   override. */
.slide-cell__num {
  display: none;
  position: absolute;
  left: -54px;
  top: 0;
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.1em;
  color: #8C8276;
  text-transform: uppercase;
}

.slide {
  width: var(--slide-w);
  height: var(--slide-h);
  background: var(--paper);
  color: var(--ink);
  position: relative;
  overflow: hidden;
  transform-origin: top left;
  transform: scale(var(--preview-scale));
  /* Subtle paper grain via SVG noise data-uri */
  background-image:
    radial-gradient(ellipse 1200px 800px at 50% 0%, rgba(255,255,255,0.35), transparent 60%),
    var(--paper-grain, none);
}

/* ── Slide chrome ──────────────────────────────────────────────────────── */
.slide__frame {
  position: absolute;
  inset: var(--pad-y) var(--pad-x);
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 0;
}

.slide__head,
.slide__foot {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}
.slide__foot { align-items: flex-end; }

.slide__head { padding-bottom: 28px; border-bottom: var(--hair) solid var(--rule); }
.slide__foot { padding-top: 28px; border-top: var(--hair) solid var(--rule); }

.serial { color: var(--ink); font-weight: 500; }
/* Allow long bylines to wrap instead of clipping (was white-space:nowrap,
   which truncated long names — finding byline-nowrap-clips-long-names). The
   name on its own line (.byline b) and the role line below still read as two
   right-aligned lines; an over-long single token breaks rather than overflow. */
.byline { text-align: right; line-height: 1.35; max-width: 360px; overflow-wrap: anywhere; }
.byline b { display: block; color: var(--ink); font-weight: 500; letter-spacing: 0.06em; }

.indicator {
  display: inline-flex;
  gap: 7px;
  align-items: center;
}
.indicator span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rule);
  display: inline-block;
}
.indicator span.is-active { background: var(--ink); transform: scale(1.4); }

.swipe {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  font-weight: 500;
}
.swipe::after {
  content: "→";
  font-family: var(--f-body);
  font-size: 26px;
  line-height: 1;
}

.slide__body {
  position: relative;
  padding: var(--gap-xl) 0 var(--gap-lg);
  display: flex;
  flex-direction: column;
}

/* Tiny tick marks at the corners of the inner frame — newspaper crop marks */
.slide__frame::before,
.slide__frame::after {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  border: var(--hair) solid var(--ink);
  opacity: 0.55;
}
.slide__frame::before {
  top: -4px; left: -4px;
  border-right: 0; border-bottom: 0;
}
.slide__frame::after {
  bottom: -4px; right: -4px;
  border-left: 0; border-top: 0;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Cover
   ────────────────────────────────────────────────────────────────────────── */
.slide--cover .slide__body {
  justify-content: flex-end;
  padding-bottom: 12px;
}
.slide--cover .kicker {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--gap-md);
}
/* Cover headline. The element is an <h2> (demoted from h1 so the app title is
   the single document h1 — see templates.js), but the look must be identical,
   so every cover-headline rule matches BOTH h1 and h2. */
.slide--cover h1,
.slide--cover h2 {
  font-family: var(--f-display);
  font-weight: 400;
  font-size: var(--t-hero);
  line-height: 0.96;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--ink);
  text-wrap: balance;
}
.slide--cover h1 em,
.slide--cover h2 em {
  font-style: italic;
  color: var(--accent);
}
.slide--cover .lede {
  font-family: var(--f-body);
  font-size: var(--t-lead);
  line-height: 1.3;
  color: var(--ink-2);
  margin-top: var(--gap-md);
  max-width: 720px;
  text-wrap: pretty;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Pull-quote
   ────────────────────────────────────────────────────────────────────────── */
.slide--quote .slide__body {
  justify-content: center;
}
.slide--quote .quote-mark {
  font-family: var(--f-display);
  font-style: italic;
  font-size: 220px;
  line-height: 0.6;
  color: var(--accent);
  margin: 0 0 -10px -8px;
  height: 110px;
  overflow: visible;
}
.slide--quote blockquote {
  font-family: var(--f-display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--t-display);
  line-height: 1.06;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0;
  text-wrap: pretty;
  max-width: 880px;
}
.slide--quote .attribution-wrap {
  margin-top: var(--gap-lg);
  display: flex;
  align-items: center;
  gap: 16px;
}
/* Attribution hairline — a REAL element (was an ::before). editable() always
   appends a permanent .field-handle child to .attribution, so the field is never
   CSS :empty; the rule has to be gated at render time (templates.js emits this
   span only when the attribution has real text). */
.slide--quote .attribution-rule {
  flex: 0 0 auto;
  width: 40px;
  height: var(--hair);
  background: var(--ink);
  display: inline-block;
}
.slide--quote .attribution {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Bullet list
   ────────────────────────────────────────────────────────────────────────── */
.slide--bullets .eyebrow,
.slide--steps .eyebrow,
.slide--imgtext .eyebrow,
.slide--statement .eyebrow,
.slide--compare .eyebrow,
.slide--checklist .eyebrow {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--gap-md);
}
.slide--bullets h2,
.slide--steps h2,
.slide--imgtext h2,
.slide--compare h2,
.slide--checklist h2 {
  font-family: var(--f-display);
  font-weight: 400;
  font-size: var(--t-title);
  line-height: 1.0;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0 0 var(--gap-lg);
  text-wrap: balance;
}
.slide--bullets h2 em,
.slide--steps h2 em,
.slide--imgtext h2 em,
.slide--compare h2 em,
.slide--checklist h2 em { font-style: italic; color: var(--accent); }

.bullets {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
  /* Closing hairline lives on the container, not on the last <li> via
     :last-child — the "+ Add row" button now sits just after the list, so a
     :last-child rule on the row would draw the bottom rule above the add affordance
     and, if add-row were ever moved into the list, leave the wrong row bordered.
     A container border-bottom is stable regardless. */
  border-bottom: var(--hair) solid var(--rule);
}
.bullets li {
  display: grid;
  grid-template-columns: 78px 1fr;
  align-items: baseline;
  gap: 22px;
  padding: 22px 0;
  border-top: var(--hair) solid var(--rule);
  font-family: var(--f-body);
  font-size: var(--t-h2);
  line-height: 1.18;
  color: var(--ink);
  letter-spacing: -0.005em;
  text-wrap: pretty;
}
.bullets li .n {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.1em;
  color: var(--accent);
  font-weight: 500;
  align-self: start;
  padding-top: 14px;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Step-by-step
   ────────────────────────────────────────────────────────────────────────── */
.steps {
  display: flex;
  flex-direction: column;
  gap: 0;
  /* Closing hairline on the container, not :last-child (see .bullets note). */
  border-bottom: var(--hair) solid var(--rule);
}
.steps .step {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 36px;
  padding: 36px 0;
  border-top: var(--hair) solid var(--rule);
}
.steps .step__num {
  font-family: var(--f-display);
  font-style: italic;
  font-size: 96px;
  line-height: 0.9;
  color: var(--accent);
}
.steps .step__title {
  font-family: var(--f-body);
  font-weight: 600;
  font-size: var(--t-h2);
  line-height: 1.1;
  margin: 6px 0 10px;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.steps .step__body {
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.4;
  color: var(--ink-2);
  text-wrap: pretty;
  max-width: 700px;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Image + Text (side by side)
   ────────────────────────────────────────────────────────────────────────── */
.slide--imgtext .slide__body {
  display: grid;
  grid-template-columns: 420px 1fr;
  gap: 56px;
  align-items: stretch;
  position: relative; /* positioning context for the split-handle */
}
.slide--imgtext.is-mirrored .slide__body {
  grid-template-columns: 1fr 420px;
}
.slide--imgtext .img-wrap {
  position: relative;
  background: var(--paper-2);
  height: 100%;
  min-height: 700px;
}
.slide--imgtext.is-mirrored .img-wrap { grid-column: 2; grid-row: 1; }
.slide--imgtext.is-mirrored .text-wrap { grid-column: 1; grid-row: 1; }

.slide--imgtext image-slot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.slide--imgtext .text-wrap {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.slide--imgtext .body-copy {
  font-family: var(--f-body);
  font-size: var(--t-lead);
  line-height: 1.32;
  color: var(--ink-2);
  margin: 0;
  text-wrap: pretty;
}
.slide--imgtext .body-copy + .body-copy { margin-top: var(--gap-md); }

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Full-bleed image with caption
   ────────────────────────────────────────────────────────────────────────── */
.slide--full {
  padding: 0;
}
.slide--full .slide__frame {
  inset: 0;
  padding: 0;
  display: block;
}
.slide--full .slide__frame::before,
.slide--full .slide__frame::after { display: none; }

.slide--full image-slot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  /* Dark fallback so the cream overlay text stays legible before a photo
     is dropped. The image-slot's own dropped image paints over this. */
  background: #1B1714;
  color: #6B6359;
}
.slide--full .full-overlay-top,
.slide--full .full-overlay-bot {
  position: absolute;
  left: 0; right: 0;
  z-index: 2;
  padding: var(--pad-y) var(--pad-x);
  color: #F1ECE0;
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  mix-blend-mode: normal;
}
.slide--full .full-overlay-top { top: 0; padding-bottom: 0; }
.slide--full .full-overlay-top::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.55), transparent);
  z-index: -1;
  pointer-events: none;
}
.slide--full .full-overlay-bot {
  bottom: 0;
  padding-top: 60px;
  padding-bottom: var(--pad-y);
  align-items: flex-end;
}
.slide--full .full-overlay-bot::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
  z-index: -1;
  pointer-events: none;
}
.slide--full .full-caption {
  position: absolute;
  left: var(--pad-x);
  bottom: 180px;
  right: var(--pad-x);
  z-index: 2;
  font-family: var(--f-display);
  font-style: italic;
  font-size: var(--t-h1);
  line-height: 1.1;
  color: #F1ECE0;
  text-wrap: balance;
  max-width: 800px;
  text-shadow: 0 2px 18px rgba(0,0,0,0.5);
}
.slide--full .full-tag {
  position: absolute;
  top: 60px;
  left: 60px;
  z-index: 2;
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #F1ECE0;
  background: var(--accent);
  padding: 10px 18px;
  white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Big stat / number (used as a quote variant)
   ────────────────────────────────────────────────────────────────────────── */
.slide--stat .slide__body {
  justify-content: center;
}
.slide--stat .stat-num {
  font-family: var(--f-display);
  font-size: 360px;
  line-height: 0.85;
  letter-spacing: -0.04em;
  color: var(--accent);
  margin: 0 0 8px -10px;
  font-weight: 400;
}
.slide--stat .stat-num em {
  font-style: italic;
}
.slide--stat .stat-label {
  font-family: var(--f-display);
  font-style: italic;
  font-size: var(--t-h1);
  line-height: 1.15;
  color: var(--ink);
  max-width: 780px;
  margin: 0;
  text-wrap: balance;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Closing / CTA
   ────────────────────────────────────────────────────────────────────────── */
.slide--close .slide__body {
  justify-content: space-between;
}
.slide--close .close-eyebrow {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--gap-md);
}
.slide--close h2 {
  font-family: var(--f-display);
  font-style: italic;
  font-weight: 400;
  font-size: 88px;
  line-height: 1.0;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0 0 var(--gap-lg);
  text-wrap: balance;
  max-width: 880px;
}
.slide--close .close-actions {
  display: flex;
  flex-direction: column;
  gap: var(--gap-md);
  border-top: var(--hair) solid var(--rule);
  padding-top: var(--gap-lg);
}
.slide--close .action {
  display: grid;
  /* The verb is a mono uppercase tag like "02 — Paste prompt". The column was
     56px, far too narrow for multi-word verbs — they broke mid-word
     ("COWO / RK"). Widen so a typical "NN — Word" sits on one line and longer
     verbs wrap at spaces (not characters). */
  grid-template-columns: 168px 1fr;
  gap: 28px;
  align-items: baseline;
  font-family: var(--f-body);
  font-size: var(--t-h2);
  line-height: 1.2;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.slide--close .action .verb {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 500;
  line-height: 1.35;
  overflow-wrap: normal; /* break only at spaces, never mid-word */
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Statement (one big declarative line)
   ────────────────────────────────────────────────────────────────────────── */
.slide--statement .slide__body { justify-content: center; }
.slide--statement .statement {
  font-family: var(--f-display);
  font-weight: 400;
  font-size: var(--t-hero);
  line-height: 1.02;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: var(--gap-md) 0 0;
  max-width: 920px;
  text-wrap: balance;
}
.slide--statement .statement em { font-style: italic; color: var(--accent); }
.slide--statement .statement-foot {
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.4;
  color: var(--muted);
  margin: var(--gap-lg) 0 0;
  max-width: 720px;
  text-wrap: pretty;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Comparison (two columns)
   ────────────────────────────────────────────────────────────────────────── */
.slide--compare .compare-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap-xl);
  margin-top: var(--gap-md);
  position: relative; /* positioning context for the split-handle */
}
.slide--compare .compare-col + .compare-col {
  border-left: var(--hair) solid var(--rule);
  padding-left: var(--gap-xl);
}

/* ── Draggable split divider (compare columns + imgtext image/text split) ────
   An edit-only bar centered on its inline `left:` (= slide.split). The hit area
   is widened (constant on-screen px regardless of --preview-scale, same trick
   the row-controls use) while the visible line stays thin. Reveal-on-frame-hover
   + brighten-to-accent live in editor.css; this is the structural base. Hidden
   in thumbnails + print there too — the split VALUE still applies (it's layout,
   not chrome), only the handle is hidden. */
.split-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  /* `left` is set inline per slide.split. Center the bar on that seam. */
  width: calc(16px / var(--preview-scale, 1));
  transform: translateX(-50%);
  cursor: col-resize;
  z-index: 6;
  touch-action: none; /* let pointer drag own the gesture, no scroll/zoom */
  background: transparent;
}
/* The visible thin line — a ::before so the wide hit area stays transparent. */
.split-handle::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: calc(2px / var(--preview-scale, 1));
  transform: translateX(-50%);
  background: var(--rule, rgba(0, 0, 0, 0.2));
  transition: background 120ms ease;
}
.slide--compare .compare-label {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--gap-sm);
}
.slide--compare .compare-items { list-style: none; padding: 0; margin: 0; border-bottom: var(--hair) solid var(--rule); }
.slide--compare .compare-items li {
  font-family: var(--f-body);
  font-size: var(--t-lead);
  line-height: 1.28;
  color: var(--ink-2);
  padding: 18px 0;
  border-top: var(--hair) solid var(--rule);
  text-wrap: pretty;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Checklist (check marks)
   ────────────────────────────────────────────────────────────────────────── */
.slide--checklist .checklist {
  list-style: none;
  padding: 0;
  margin: 0;
  /* Closing hairline on the container, not :last-child (see .bullets note). */
  border-bottom: var(--hair) solid var(--rule);
}
.slide--checklist .check-item {
  display: grid;
  grid-template-columns: 64px 1fr;
  align-items: baseline;
  gap: 22px;
  padding: 22px 0;
  border-top: var(--hair) solid var(--rule);
  font-family: var(--f-body);
  font-size: var(--t-h2);
  line-height: 1.18;
  color: var(--ink);
  text-wrap: pretty;
}
.slide--checklist .check-mark {
  font-size: 38px;
  line-height: 1;
  color: var(--accent);
  font-weight: 700;
  align-self: start;
  padding-top: 4px;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Section divider (chapter break)
   ────────────────────────────────────────────────────────────────────────── */
.slide--divider .slide__body { justify-content: center; }
.slide--divider .divider-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: var(--gap-md);
}
.slide--divider .divider-kicker {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
}
.slide--divider .divider-part {
  font-family: var(--f-display);
  font-size: 220px;
  line-height: 0.8;
  letter-spacing: -0.04em;
  color: var(--accent);
}
.slide--divider .divider-title {
  font-family: var(--f-display);
  font-weight: 400;
  font-size: var(--t-display);
  line-height: 1.0;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0;
  max-width: 880px;
  text-wrap: balance;
}
.slide--divider .divider-title em { font-style: italic; color: var(--accent); }

/* ─────────────────────────────────────────────────────────────────────────
   TEMPLATE: Full background (dimmable). Reuses the .slide--full chrome; adds a
   black scrim between the photo (z 0) and the overlaid text (z 2).
   ────────────────────────────────────────────────────────────────────────── */
.slide--fullbg .fullbg-dim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #000;
  pointer-events: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   Print: every slide on its own 1080×1350 page
   ────────────────────────────────────────────────────────────────────────── */
@media print {
  @page { size: 1080px 1350px; margin: 0; }
  html, body {
    width: 1080px;
    height: auto;
    min-height: 0;
    margin: 0;
    padding: 0;
    background: #fff;
    overflow: visible;
  }
  /* Tear the grid shell down for paper. `display:block` already neutralises
     the grid (so grid-template-columns/rows never apply on a 1080px page), but
     null the template/gap/padding explicitly so no residual shell inset shifts
     the page box. */
  body {
    display: block;
    grid-template-columns: none !important;
    grid-template-rows: none !important;
    column-gap: 0 !important;
    padding: 0 !important;
  }
  /* Belt + suspenders for hiding screen-only chrome. Some print engines
     (Edge on macOS, Safari) honour `display: none` differently when the
     element is also `position: fixed`; visibility + display + position
     together kills it in all observed paths. The Tweaks panel may now dock
     position:static inside its grid cell (no longer always fixed), so the
     display:none/visibility:hidden pair must kill it in EITHER state. */
  .app__head, .app__foot, .twk-panel, .edt, #tweaks-root, [data-no-print] {
    display: none !important;
    visibility: hidden !important;
  }
  .app, .slides {
    display: block !important;
    padding: 0 !important;
    margin: 0 !important;
    gap: 0 !important;
  }
  /* Every cell is the page size, and clamps anything that bleeds past 1350px
     (a few pixels from antialiasing / box-shadow / sub-pixel layout) so the
     print engine doesn't drop a phantom page break. */
  .slide-cell {
    display: block !important;
    width: 1080px;
    height: 1350px;
    margin: 0;
    box-shadow: none;
    overflow: hidden;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  /* Explicit `avoid` on the first cell — some engines (notably macOS Edge /
     Safari) insert a phantom blank page before the first cell otherwise. */
  .slide-cell:first-child {
    page-break-before: avoid;
    break-before: avoid;
  }
  /* Break after every cell except the last — otherwise the engine adds an
     empty trailing page. */
  .slide-cell:not(:last-child) {
    page-break-after: always;
    break-after: page;
  }
  .slide-cell:last-child {
    page-break-after: auto;
    break-after: auto;
  }
  .slide-cell__num { display: none !important; }
  .slide { transform: none; margin: 0; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Responsive preview scale
   ────────────────────────────────────────────────────────────────────────── */

/* Intermediate band (1100–1320px): at 1100px the shell switches to the
   3-column grid (rail · stage · tweaks — see the matching panel-width band in
   editor.css). The slide preview is a fixed-size cell, 1080·--preview-scale px
   wide, centred in the stage track. At the flat 0.62 the cell is 669.6px —
   wider than the stage track until ~1290px — so it spills out of the [stage]
   track and underlaps the Pages rail (.edt) and the docked Tweaks panel
   (#tweaks-root .twk-panel). Step the scale down so the whole slide stays
   visible AND inside its track across the band; >1320px the wider default
   panels return and the base 0.62 fits again. (The cell is sized off a unitless
   scale via transform:scale(), so a fluid clamp() can't be derived from the
   track width in pure CSS — hence discrete steps, like the ≤720px rule below.) */
@media (min-width: 1100px) and (max-width: 1199px) { .app { --preview-scale: 0.44; } }
@media (min-width: 1200px) and (max-width: 1259px) { .app { --preview-scale: 0.52; } }
@media (min-width: 1260px) and (max-width: 1320px) { .app { --preview-scale: 0.58; } }

@media (max-width: 720px) {
  .app { --preview-scale: 0.32; padding: 24px 16px 80px; }
  .slide-cell__num { left: -28px; font-size: 11px; }
}
