/* Shared styles for the SEO satellite pages (/offline-document-editor,
   /no-signup-document-editor, /open/*, /convert/*, and their /zh-CN/
   mirrors). Utilitarian document layout, but on the same design system as the
   homepage: every value comes from the ranui token layer (/ran-tokens.css,
   loaded before this file), the chrome is real ranui components registered by
   the /ranui-iife/<name>.iife.js bundles (<r-button>), and the visual language
   mirrors home.css — hairline rules, mono type for machine facts, blue spent only on
   the primary action. Dark mode comes from the token layer for free. */

* {
  box-sizing: border-box;
}
body {
  margin: 0;
  background: var(--ran-color-bg);
  color: var(--ran-color-text);
  font-family: var(--ran-font-family);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a {
  color: var(--ran-color-link);
}
a:focus-visible {
  outline: 2px solid var(--ran-color-link);
  outline-offset: 2px;
}

/* ---------- top bar (mirrors the homepage bar) ---------- */
header.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ran-space-4);
  padding: var(--ran-space-4) clamp(20px, 5vw, 56px);
  border-bottom: 1px solid var(--ran-color-border);
}
header.bar .brand {
  display: inline-flex;
  align-items: center;
  gap: var(--ran-space-2);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.01em;
  color: var(--ran-color-text);
  text-decoration: none;
}
header.bar .logo {
  width: 24px;
  height: 24px;
  border-radius: var(--ran-radius-sm);
  /* monochrome mark (Geist): ink on page bg, inverts with the theme */
  background: var(--ran-color-text);
  display: inline-grid;
  place-items: center;
  color: var(--ran-color-bg);
  font-size: 13px;
  font-weight: 700;
}
header.bar nav {
  display: flex;
  align-items: center;
  gap: var(--ran-space-1);
}
header.bar nav a {
  display: inline-flex;
  align-items: center;
  gap: var(--ran-space-2);
  padding: var(--ran-space-2) var(--ran-space-3);
  border-radius: var(--ran-radius-sm);
  font-size: 14px;
  color: var(--ran-color-text-secondary);
  text-decoration: none;
  transition: 0.15s ease;
}
header.bar nav a:hover {
  color: var(--ran-color-text);
  background: var(--ran-color-bg-hover);
}
.ghmark {
  width: 15px;
  height: 15px;
  fill: currentColor;
  flex: none;
}
/* language switch: same ranui <r-select> as the homepages, wired by the shared
   /lang-switch.js (targets declared as data-href on the options) */
.lang-wrap {
  display: inline-flex;
  align-items: center;
  gap: var(--ran-space-1);
  padding-left: var(--ran-space-1);
}
.langmark {
  width: 15px;
  height: 15px;
  color: var(--ran-color-text-secondary);
  flex: none;
}
r-select.lang-select {
  display: inline-block;
  /* Fits the longest endonym in the menu. The component clips its own label
     (overflow: hidden inside the shadow root) and sizes the dropdown panel to
     the trigger, so a trigger too narrow for "Português" cuts the word in both
     places at once. The number is checked, not guessed: language-menu.spec.ts
     opens every locale and fails if any label is clipped. */
  min-width: 132px;
  font-size: 14px;
  /* Matches the nav links beside it (14px on space-2/space-3 padding); the
     44px default stood a head taller than everything else in the bar. */
  height: 34px;
}
/* hide the raw option list pre-upgrade; the reserved width avoids layout shift */
r-select.lang-select:not(:defined) {
  visibility: hidden;
}

/* ---------- language menu (ranui r-select) ----------
   The site's own palette applied to the component's variables. The panel is
   portalled to <body>, so these have to be declared at the root: scoped to the
   trigger they would style the trigger and never reach the menu.

   Kept byte-identical in home.css and landing.css (the homepage does not load
   landing.css); test/unit/design-contract.test.ts compares the two blocks. */
:root {
  --ran-dropdown-padding: 4px;
  /* 10px, not the component's 12: the panel is 76px wide and two rows tall,
     and at radius-md its corners eat into the rows inside it. */
  --ran-dropdown-border-radius: 10px;
  --ran-dropdown-box-shadow:
    0 0 0 1px var(--ran-color-border), 0 8px 24px -6px color-mix(in srgb, var(--ran-color-text) 18%, transparent);
  --ran-dropdown-option-item-padding: 6px 10px;
  --ran-dropdown-option-item-border-radius: var(--ran-radius-sm);
  --ran-dropdown-option-item-font-size: 14px;
  --ran-dropdown-option-item-content-font-size: 14px;
  --ran-dropdown-option-item-hover-background-color: var(--ran-color-bg-hover);
  /* Selection is weight plus a neutral ground, not a blue fill: on this site
     blue means a link, and every row of this menu is one. */
  --ran-dropdown-option-active-background-color: var(--ran-color-bg-active);
  --ran-dropdown-option-active-hover-background-color: var(--ran-color-bg-active);
  --ran-dropdown-option-active-font-weight: 600;
}

@media (max-width: 620px) {
  /* Phone: the bar is brand + GitHub + a language name, and at 390px the
     language trigger (wide enough for "Português") pushed the caret off the
     viewport and broke the brand onto two lines. GitHub loses: it is one line
     down in the footer of every page, while the language switch is the only
     way to change the language. */
  header.bar nav > a[href*='github.com'] {
    display: none;
  }
}

/* ---------- article column ---------- */
.wrap {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--ran-space-6) clamp(20px, 5vw, 56px) var(--ran-space-10);
}

/* ---------- two-column page frame (article + sticky sidebar) ----------
   The reading column stays at 720px / ~66 characters -- that is the number the
   typography wants and widening it would trade readability for filled pixels.
   What a wide viewport gets instead is a second column, the way documentation
   sites do it (Stripe, Vercel, MDN all keep a ~700px article and put an "on this
   page" rail beside it): the call to action stops disappearing after the first
   screen, the page's own sections stay reachable, and the sibling pages get a
   real internal link rather than only a footer row.

   Mobile-first: below the breakpoint this is a plain block and the rail is not
   rendered at all -- the CTA is already on screen there, and a table of contents
   on a phone is a list of links between the reader and the text. */
.side {
  display: none;
}
/* Below the breakpoint the footer keeps the article's own column and gutters;
   the media query below widens it to the frame. Order matters -- both rules
   have the same specificity, so the wide one has to come second. */
.page-foot {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 clamp(20px, 5vw, 56px) var(--ran-space-10);
}
/* The ONLYOFFICE trademark notice. Section 7(e) of the vendor's AGPL terms
   declines to grant any rights under trademark law, so every page states whose
   mark it is and that this site is not their product. Muted and last: it is a
   legal notice, not navigation. */
.page-foot .tm {
  margin: var(--ran-space-4) 0 0;
  max-width: 72ch;
  color: var(--ran-color-text-secondary);
  font-size: 12.5px;
  line-height: 1.6;
}
@media (min-width: 1081px) {
  .page {
    display: grid;
    /* 660, not 720: the old single-column page was a 720px box with 56px
       gutters inside it, so the text itself was ~608px / 66 characters. Handing
       the column the full 720 would have pushed the measure to 77 -- past the
       45-75 band the rest of the site is tuned to. 660 lands at 71, the same
       measure the homepage reads at. */
    grid-template-columns: minmax(0, 660px) minmax(0, 284px);
    justify-content: center;
    gap: clamp(40px, 5vw, 96px);
    max-width: 1152px;
    margin: 0 auto;
    padding-inline: clamp(20px, 5vw, 56px);
  }
  /* the frame owns the horizontal padding now; the column keeps its own top
     and bottom rhythm */
  .page > .wrap {
    padding-inline: 0;
  }
  .side {
    display: block;
    position: sticky;
    /* clears the top bar and leaves the same air the article has */
    top: var(--ran-space-8);
    align-self: start;
    padding-top: var(--ran-space-6);
    /* /help lists nine sections; a rail taller than the viewport would clip
       its last links with no way to reach them. */
    max-height: calc(100vh - var(--ran-space-16));
    overflow-y: auto;
    scrollbar-width: thin;
  }
  .page-foot {
    max-width: 1152px;
    margin-inline: auto;
    padding-inline: clamp(20px, 5vw, 56px);
  }
}
/* The rail is rules and type, like the rest of the site -- no panel, no fill. */
.side-cta .cta {
  display: block;
  margin: 0;
}
/* Full-bleed pill: the width has to reach the exported parts too. Sizing only
   the host leaves the shadow it paints as a rectangle behind a rounded button
   -- a straight line poking out past both ends (same trap as the homepage CTA). */
.side-cta r-button {
  display: block;
  width: 100%;
}
.side-cta r-button::part(button),
.side-cta r-button::part(content) {
  width: 100%;
  box-sizing: border-box;
  justify-content: center;
}
.side-note {
  display: block;
  margin-top: var(--ran-space-3);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ran-color-text-secondary);
}
.side-block {
  display: block;
  margin-top: var(--ran-space-6);
  padding-top: var(--ran-space-4);
  border-top: 1px solid var(--ran-color-border);
}
.side-label {
  display: block;
  margin-bottom: var(--ran-space-2);
  font: 600 11px/1 var(--ran-font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ran-color-text-secondary);
}
.side-block a {
  display: block;
  padding: 5px 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--ran-color-text-secondary);
  text-decoration: none;
  transition: color 0.15s ease;
}
.side-block a:hover {
  color: var(--ran-color-text);
}
.eyebrow {
  margin: var(--ran-space-8) 0 0;
  font: 600 12px/1 var(--ran-font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* gray mono label — blue is reserved for links */
  color: var(--ran-color-text-secondary);
}
h1 {
  font-size: clamp(28px, 5vw, 40px);
  line-height: 1.15;
  letter-spacing: -0.03em;
  margin: var(--ran-space-3) 0 var(--ran-space-3);
  text-wrap: balance;
}
h2 {
  font-size: 21px;
  letter-spacing: -0.02em;
  margin: var(--ran-space-10) 0 var(--ran-space-4);
  padding-bottom: var(--ran-space-3);
  border-bottom: 1px solid var(--ran-color-border);
}
p {
  margin: var(--ran-space-3) 0;
}
.lead {
  font-size: 18px;
  color: var(--ran-color-text-secondary);
  margin: 0 0 var(--ran-space-4);
}

/* CTA: a real <r-button> wrapped in a link (static pages navigate, not script) */
.cta {
  display: inline-block;
  margin: var(--ran-space-4) 0 var(--ran-space-5, 20px);
  text-decoration: none;
}
/* r-button exports parts "button" (container) and "content" (padding/border/
   typography). The :not(:defined) fallback below must stay pixel-identical to
   these values or the custom-element upgrade flashes on load. */
/* The raised shadow ranui paints sits on the HOST element, while the radius
   below only reaches the exported parts inside the shadow DOM. The host keeps
   its own radius (ranui does not set one), so a pill ends up wrapped in a
   rectangular shadow: a straight line under the button, poking out past both
   rounded ends. Barely visible at ranui's 6px default, obvious at --ran-radius-full.
   Give the host the same radius as the thing it wraps. */
.cta r-button,
.cta r-button::part(button) {
  border-radius: var(--ran-radius-full);
}
.cta r-button::part(content) {
  border-radius: var(--ran-radius-full);
  padding: var(--ran-space-3) var(--ran-space-6);
  font-size: 15.5px;
  font-weight: 600;
}
/* pre-upgrade fallback so the CTA is a styled, clickable button even before
   (or without) the /ranui-iife/*.iife.js bundles — same progressive-enhancement
   idea as the static-page fallbacks on the homepage. Mirrors type="primary". */
.cta r-button:not(:defined) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--ran-space-3) var(--ran-space-6);
  border-radius: var(--ran-radius-full);
  border: 1px solid var(--ran-color-primary);
  background: var(--ran-color-primary);
  color: var(--ran-color-primary-text);
  font-weight: 600;
  font-size: 15.5px;
  line-height: 22px; /* matches .ran-btn-content's default line-height */
}

ul {
  padding-left: 20px;
  margin: var(--ran-space-4) 0;
}
li {
  margin: var(--ran-space-2) 0;
}
li::marker {
  color: var(--ran-color-border-hover);
}

/* ---------- open-source note ----------
   An aside inside the article, so it is bounded by a rule down its left edge
   rather than by a card. A filled, bordered box interrupts the reading column
   and reads as a different kind of content; this one is still prose, just set
   apart -- and it keeps the satellite pages free of card chrome, like the
   homepage. */
.oss {
  margin: var(--ran-space-8) 0;
  padding-left: var(--ran-space-5, 20px);
  border-left: 2px solid var(--ran-color-border);
  font-size: 15px;
  color: var(--ran-color-text-secondary);
}
.oss strong {
  color: var(--ran-color-text);
}
.oss a {
  font-weight: 600;
}

/* ---------- faq: hairline per question (mirrors homepage FAQ) ---------- */
.faq h3 {
  font-size: 16.5px;
  letter-spacing: -0.01em;
  margin: 0;
  padding: var(--ran-space-4) 0 0;
  border-top: 1px solid var(--ran-color-border);
}
.faq h3:first-child {
  border-top: none;
  padding-top: 0;
}
.faq p {
  margin: var(--ran-space-1) 0 var(--ran-space-4);
  color: var(--ran-color-text-secondary);
  font-size: 15px;
}
h2.faq {
  border-bottom: 1px solid var(--ran-color-border);
}

/* ---------- footer ---------- */
footer {
  margin-top: var(--ran-space-16);
  padding-top: var(--ran-space-4);
  border-top: 1px solid var(--ran-color-border);
  color: var(--ran-color-text-secondary);
  font-size: 13.5px;
}
footer a {
  color: var(--ran-color-text-secondary);
  text-decoration: none;
  margin-right: var(--ran-space-4);
}
footer a:hover {
  color: var(--ran-color-text);
}

/* ---------- theme switch (footer) ----------
   Real ranui <r-theme-switch>. The pre-upgrade fallback reserves the pill's
   exact footprint (3×28px buttons + gaps + padding + border) — no shift. */
r-theme-switch.theme-switch {
  vertical-align: middle;
}
r-theme-switch.theme-switch:not(:defined) {
  display: inline-block;
  width: 94px;
  height: 34px;
  border: 1px solid var(--ran-color-border);
  border-radius: var(--ran-radius-full);
}
/* footer rows on the satellites are plain text; give the pill its own line spacing */
footer .theme-switch {
  margin-top: var(--ran-space-4);
}

/* ---------- generated markdown pages (/help, /changelog; bin/build-pages.mjs) ----------
   Same column and type as the satellites; these rules only add what markdown
   emits that the hand-written pages never did: h3 sections, code, tables,
   quotes, a small table of contents. All values from the token layer. */
.doc article h3 {
  font-size: 16.5px;
  letter-spacing: -0.01em;
  margin: var(--ran-space-6) 0 var(--ran-space-2);
}
.doc article h4 {
  font-size: 15px;
  margin: var(--ran-space-4) 0 var(--ran-space-2);
}
.doc article :is(h2, h3, h4) a {
  color: inherit;
  text-decoration: none;
}
.doc code,
.wrap article code {
  font-family: var(--ran-font-mono);
  font-size: 0.9em;
  padding: 1px 5px;
  border-radius: var(--ran-radius-sm);
  background: var(--ran-color-bg-subtle);
  border: 1px solid var(--ran-color-border);
}
.doc pre,
.wrap article pre {
  margin: var(--ran-space-4) 0;
  padding: var(--ran-space-4);
  overflow-x: auto;
  border-radius: var(--ran-radius-md);
  background: var(--ran-color-bg-subtle);
  border: 1px solid var(--ran-color-border);
  font-size: 13px;
  line-height: 1.55;
}
.doc pre code,
.wrap article pre code {
  padding: 0;
  border: 0;
  background: none;
  font-size: inherit;
}
.doc table,
.wrap article table {
  width: 100%;
  border-collapse: collapse;
  margin: var(--ran-space-4) 0;
  font-size: 14.5px;
  display: block;
  overflow-x: auto;
}
.doc th,
.doc td,
.wrap article th,
.wrap article td {
  text-align: start;
  vertical-align: top;
  padding: var(--ran-space-2) var(--ran-space-3);
  border-bottom: 1px solid var(--ran-color-border);
}
.doc th,
.wrap article th {
  font-weight: 600;
  color: var(--ran-color-text-secondary);
  font-size: 13px;
  letter-spacing: 0.02em;
}
.doc blockquote {
  margin: var(--ran-space-4) 0;
  padding: var(--ran-space-2) var(--ran-space-4);
  border-inline-start: 3px solid var(--ran-color-border-hover);
  color: var(--ran-color-text-secondary);
}
.doc ol {
  padding-inline-start: 22px;
  margin: var(--ran-space-4) 0;
}
.doc hr {
  border: 0;
  border-top: 1px solid var(--ran-color-border);
  margin: var(--ran-space-8) 0;
}
.doc img {
  max-width: 100%;
  height: auto;
}
.doc .notice {
  padding: var(--ran-space-2) var(--ran-space-3);
  border-radius: var(--ran-radius-sm);
  background: var(--ran-color-bg-subtle);
  border: 1px solid var(--ran-color-border);
  color: var(--ran-color-text-secondary);
  font-size: 14px;
}
.doc .source {
  margin-top: var(--ran-space-8);
  font-family: var(--ran-font-mono);
  font-size: 12px;
  color: var(--ran-color-text-secondary);
}
